8
votes

Is there any way to make spring-data-elasticsearch to work for multitenant application?

I've made it to work without multitenancy, but I don't know how can I have multiple indices or multiple nodes for each tenant? I want to know if there is any way to define different index name for each tenant or to add transient property in my entity class which is annotated properly with @Document(...). When I tried to do that problem was that @Transient is also marked in ElasticSearchRepository. Any idea?

4
can you please elaborate more ? when you say multi tanant, is it for searching on multiple indices ?Mohsin Husen
Yes I would like to have multiple indices for each tenant. With spring-data-elasticsearch I haven't found any solution like that. So any other solution like multiple nodes or whatever would be appropriate for memiroslav_mijajlovic
you wanna configure elasticsearch in single node arch where more than one user @ a time [or] multi node arch??BlackPOP
single node arch with more than one tenantsmiroslav_mijajlovic

4 Answers

4
votes

Here's the solution I made to this problem. By default, We would add an index with our POJO annotation of @Document which is okay.However there are cases where we would want to have differen indexes per client so I decided to create them myself. I've used the ElasticSearch Template to create indexes for different tenants rather than relying on Spring Data ElasticSearch repo for saving. Here's what I did

    IndexQuery indexQuery = new IndexQueryBuilder()
                        .withId("ID")
                        .withIndexName("yourtenant")
                        .withType("yourtype")
                        .withObject(obj)
                        .build();

    es.index(indexQuery)
3
votes

First you've got to understand how Elasticsearch (and especially Lucene) store your data.

Elasticsearch's naming convention "index" and "type" is a bit misleading and most likely not what you first thought!


If you create a type (id, field1, field2) within an index in Elasticsearch, it will create something similar to a SQL Table:

id     | field1 | field2
-------------------------
string | int    | boolean

What you might not expect is, what happens when you add a second type (id, type2field) to that index. The index mapping will become:

id     | field1 | field2  | type2field
--------------------------------------
string | int    | boolean | string

This happens, because there's no type mapping - even if Elasticsearch will make it look like that. There's only a mapping at index level! This way, you will most likely end up having a lot of empty fields.


Though in general and especially for a multi tenency setup, you should create an index per class - not type! You should use the type for separating similar shaped data, i.e. use types for your tenants. Or add an additional field to your mapping for identifying the tenant.


Read more about it here: https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping.html#_type_takeaways

2
votes

I've made solution to this problem. It might not be the best solution but I didn't found anything else. I've added field tenantName to my indexed classes and marked it with annotation @javax.persistence.Transient instead of @org.springframework.data.annotation.Transient. And after that I am making my search queries with condition that tenant must be tenant to which current user belongs.

1
votes

I found quite an easy solution with SpEL for prefixing indexes like

@Document(indexName = "#{@prefixProvider.getPrefix()}_foo", type="bar")

prefixProvider being just a regular spring bean.