7

Hi I am using elastic search Spring data. Domain structure of my project keeps on changing.So I have to drop the index in order to change the mapping every time. To overcome this problem, I am using Aliases. I created an Alias using:

elasticsearchTemplate.createIndex(Test.class);
elasticsearchTemplate.putMapping(Test.class);

    String aliasName = "test-alias";
    AliasQuery aliasQuery = new AliasBuilder()
            .withIndexName("test")
            .withAliasName(aliasName).build();

    elasticsearchTemplate.addAlias(aliasQuery);

I have a test class:

import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldIndex
import org.springframework.data.elasticsearch.annotations.FieldType
import org.springframework.data.elasticsearch.annotations.Setting


@Document(indexName = "test", type = "test")
@Setting(settingPath = 'elasticSearchSettings/analyzer.json')
class Test  extends BaseEntity{

@Id
@Field(type = FieldType.String, index = FieldIndex.not_analyzed)
String id

@Field(type = FieldType.String, index = FieldIndex.analyzed, indexAnalyzer = "generic_analyzer", searchAnalyzer = "generic_analyzer")
String firstName



}

TestRepository Class:

package com.as.core.repositories

import com.as.core.entities.Test
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository

interface TestRepository extends ElasticsearchRepository<Test, String>          
{


}

My question is how can I read from alias instead of the index itself? Does write operation also takes place on alias. I have looked at following link: https://www.elastic.co/guide/en/elasticsearch/guide/current/index-aliases.html#index-aliases It says that we will have to interact the alias instead of the actual index.How to achieve this using Elasticsearch Spring data Java API.

Richa
  • 7,419
  • 6
  • 25
  • 34

2 Answers2

10

I have worked around this limitation by using the ElasticsearchTemplate in the repository class associated with the object (although it would be much nicer if there was a way to specify an alias name on the entity itself).

The way it works is to create a custom repository interface. In your case it would be TestRepositoryCustom:

public interface TestRepositoryCustom
{
    Test> findByCustom(...);
}

Then implement this interface appending 'Impl' to the end of the base repository name:

public class TestRepositoryImpl implements TestRepositoryCustom
{
    Page<Test> findByCustom(Pageable pageable, ...)
    {
        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
        FilterBuilder filter = FilterBuilders.staticMethodsToBuildFilters;
        /*
         * Your code here to setup your query
        */

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withQuery(boolQuery).withFilter(filter).withPageable(pageable); 

        //These two are the crucial elements that will allow the search to look up based on alias
        builder.withIndices("test-alias");
        builder.withTypes("test");

        //Execute the query
        SearchQuery searchQuery = builder.build();
        return elasticSearchTemplate.queryForPage(searchQuery, Test.class);
    }
}

Finally in your base JPA repsitory interface, TestRepository, extend the TestRepositoryCustom interface to get access to any methods on your custom interface from your repository bean.

public interface TestRepository extends ElasticsearchRepository<Consultant, String>, TestRepositoryCustom
{
}

What I would really like to see is an annotation on the entity like:

@Document(aliasName="test-alias")

This would just work in the background to provide searching on this index out of the gate so that all the jpa queries would just work regardless of the index name.

Tim Schimandle
  • 792
  • 11
  • 22
  • Here is an open issue for that: https://jira.spring.io/browse/DATAES-192 – Anton Bessonov Jan 20 '18 at 01:51
  • On the other hand, if the number of aliases is unknown at the time you create the mapping, we need something else than a annotation like you propose. For instance, if you need an alias for each users (to implement multi-tenancy). Than I would like to see something like: @Document(aliasKey="user_id") Than, you can PUT any document as the following (Spring data) could create the alias if it is not present. PUT /user123/post/1 { "user_id": "user123", "title": "Easy recipe for ginger nuts", ... } – Erick Audet Jan 13 '21 at 03:46
1

Spring-data-elasticsearch supports finding documents in an alias. We were able to make version 3.2.6.RELEASE read documents annotated with

@Document(
    indexName = "alias",
    createIndex = false,
    type = '_doc'
)

from a Spring Data ElasticsearchRepository backed by a ElasticsearchRestTemplate

Jordan Grant
  • 860
  • 7
  • 12