使用Spring-Data Elasticsearch在Elasticsearch中动态创建索引名称

14

我有一个使用场景,需要在Elasticsearch中按月创建索引。想法是按月创建索引,以便于维护,并且可以在过期时删除。为了实现这一点,我使用了spring-batch,并且有一个每月的任务,将按月创建索引。对于Elasticsearch-Java集成,我使用了Spring-Data Elasticsearch实现。我现在面临的问题是,我无法找出如何使用Entity对象提供动态名称来创建索引和映射。我的当前实现是考虑单个索引进行的。请查看下面的代码,这是我用来创建索引的。

elasticsearchTemplate.createIndex(SingleChat.class);
elasticsearchTemplate.putMapping(SingleChat.class);
elasticsearchTemplate.refresh(SingleChat.class, true);

而 SingleChat 是我的实体类

@Document(indexName="singlemsgtemp_#{jobParameters['MONTH']}",type="singlechat")
public class SingleChat {
    @org.springframework.data.annotation.Id
    String Id;
    @Field(type = FieldType.String)
    String conservationId;
    @Field(type = FieldType.String)
    String from;
    @Field(type = FieldType.String)
    String to;
    @Field(type = FieldType.String)
    String msgContent; 
    @Field(type = FieldType.String)
    String sessionId;
    @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true, format = DateFormat.date_hour_minute_second_millis)
    Date postedDate;
    @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true, format = DateFormat.date_hour_minute_second_millis)
    Date expireDate;
}   

但是它并没有像预期的那样工作。我正在尝试其他一些方法。但我愿意接受建议。同时,请随意评论我的当前方法,它是否可行。如果需要更多细节,请告诉我。

2个回答

10

在我的项目中,我们会在索引名称或类型名称更改时将其存储到数据库中。

现在我是通过以下方式动态地获取索引和类型:

第一种解决方案

  • 1)在配置文件中创建一个返回someProperty值的Bean。在这里,我使用@Value注解从数据库或属性文件中注入了somePropertyValue:

@Value("${config.somePropertyValue}")
private String somePropertyValue;

@Bean
public String somePropertyValue(){
    return somePropertyValue;
}
  • 2)完成这一步后,就可以像这样将somePropertyValue注入@Document注释中:

  • @Document(index = "#{@somePropertyValue}")
    public class Foobar {
        //...
    }
    

    第二种解决方案

    • 1) 在bean中创建getter和setter方法:

    @Component
    public class config{
         @Value("${config.somePropertyValue}")
         private String somePropertyValue;
    
         public String getSomePropertyValue() {
           return somePropertyValue;
         }
        public void setSomePropertyValue(String somePropertyValue) {
           this.somePropertyValue = somePropertyValue;
        }
    }
    
  • 2) 在此之后,可以将 somePropertyValue 注入到 @Document 注释中,如下所示:

  • @Document(index = "#{config.somePropertyValue}")
    public class Foobar {
        //...
    }
    

    我不得不将 spring-data-commons 添加到我的项目中,以便使用 org.springframework.data.spel.ExpressionDependencies。这不包含在 spring-data-elasticsearch 中。 - nonNumericalFloat

    5

    我在我的应用程序中所做的是使用ElasticSearchTemplate创建动态索引名称,然后将别名指向我创建的新索引,然后丢弃旧索引。

    esTemplate.createIndex(newIndexName, loadfromFromFile(settingsFileName));
    esTemplate.putMapping(newIndexName, "MYTYPE", loadfromFromFile(mappingFileName));
    

    我不使用来自我的类的映射和设置,因为我需要它是动态的。

        protected String loadFromFile(String fileName) throws IllegalStateException {
           StringBuilder buffer = new StringBuilder(2048);
           try {
               InputStream is = getClass().getResourceAsStream(fileName);
               LineNumberReader reader = new LineNumberReader(new InputStreamReader(is));
               while (reader.ready()) {
                   buffer.append(reader.readLine());
                   buffer.append(' ');
               }
           } catch (Exception e) {
               throw new IllegalStateException("couldn't load file " + fileName, e);
           }
           return buffer.toString();
       }
    

    感谢Thiago的回复,我会尝试这个方法。只是想确认一下,loadFromFile(mapping/setting)会返回JSON格式的字符串,对吗?另外,您能否分享一下添加索引到别名的代码片段。我正在尝试使用AliasQueryBuild和AliasQuery来实现,您是否也是用同样的方法,或者还有其他方法可以实现呢? - sagar27
    @sagar27,该方法现在已经存在。 - Thiago
    那对我有用,传递JSON映射文件而不是模型对象。目前使用别名获取数据也可以工作。谢谢Thiago。 - sagar27
    @Thiago,我可以在实体上定义@Document注释而不需要indexName属性吗?这种方法是否存在任何配置问题? - andPat
    你可以这样做,只是你不一定非得这么做。我没有遇到任何配置问题。 - Thiago
    我可以问你一些东西吗?你如何加载JSON文件?那是哪种方法?你能否更新您的帖子与它? - Carlos Vázquez Losada

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接