Spring boot 实现 Elasticsearch 动态创建索引

查找了很多方法都是通过Spring EL表达式实现 @Document(IndexName="#{demo.getIndexName}")

这种方式的问题在于没法解决数据库里生成的序号,例如我希望通过公司ID生成索引编号。后来在外网上找到一个大佬提出的解决方案,这位大佬把两种方案都实现了一遍。

  • 通过entityId自定义index

Use an index name defined by the entity to store data in Spring Data Elasticsearch 4.0

  • 通过SpEL动态生成index

How to provide a dynamic index name in Spring Data Elasticsearch using SpEL

我这里按照entity的方式实现了需求

elasticsearch 版本7.17.3

springboot版本2.7.1

Bean


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Document(indexName = ElasticSearchIndices.ES_INDEX_TROUBLES_COMPANY+"_*",createIndex = false)
public class CompanyTroubleshootingBean implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    @JsonSerialize(
            using = ToStringSerializer.class
    )
    @Field(type = FieldType.Keyword , store = true)
    private Long id;

    @Field(type = FieldType.Text, analyzer = "ik_smart")
    private String content;

    @Field(type = FieldType.Text, analyzer = "ik_smart")
    private String searchKeyword;
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String contentMaxWord;
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String searchKeywordMaxWord;

    private Integer useCounts;

    //也是内容  这个内容不能分词查询
    @Field(type = FieldType.Keyword)
    private String keywordContent;

    @Field(type = FieldType.Keyword)
    private Integer catalogId;

    public String getContentMaxWord() {
        return content;
    }
    //私有化set方法,让该属性只读
    private void setContentMaxWord(String contentMaxWord) {
        this.content = contentMaxWord;
    }

    public String getSearchKeywordMaxWord() {
        return searchKeyword;
    }
    //私有化set方法,让该属性只读
    private void setSearchKeywordMaxWord(String searchKeywordMaxWord) {
        this.searchKeyword = searchKeywordMaxWord;
    }


    /**
     * 公司ID
     */
    private Integer companyId;

    /**
     * 平台的解决方案ID
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    @JsonSerialize(
            using = ToStringSerializer.class
    )
    private Long platformTroubleshootingId;



}

接口

//相当于重新定义了一个repository
public interface CompanyTroubleshootElasticRepository<T> {
    <S extends T> S save(S entity);

    <S extends T> Iterable<S> save(Iterable<S> entities);
}

实现类

package online.ejiang.service.impl.troubleshooting;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import online.ejiang.enums.ElasticSearchIndices;
import online.ejiang.pojo.elasticsearch.CompanyTroubleshootingBean;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;

import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 * 公司故障排除及定价 服务实现类
 *
 * </p>clo
 *
 * @author Phil
 * @since 2020-07-22
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CompanyTroubleshootingRepositoryImpl implements CompanyTroubleshootElasticRepository<CompanyTroubleshootingBean> {

    private final ElasticsearchOperations operations;

    @Nullable
    private Document mapping;

    @Override
    public <S extends CompanyTroubleshootingBean> S save(S entity) {
        IndexCoordinates indexCoordinates = getIndexCoordinates(entity);
        S saved = operations.save(entity, indexCoordinates);
        operations.indexOps(indexCoordinates).refresh();
        return saved;
    }

    @Override
    public <S extends CompanyTroubleshootingBean> Iterable<S> save(Iterable<S> entities) {
        if (entities != null && entities.iterator().hasNext()) {
            IndexCoordinates indexCoordinates = getIndexCoordinates(entities.iterator().next());
            Iterable<S> saved = operations.save(entities, indexCoordinates);
            operations.indexOps(indexCoordinates).refresh();
            return saved;
        }
        return null;
    }

    @NonNull
    private <S extends CompanyTroubleshootingBean> IndexCoordinates getIndexCoordinates(S entity) {
        String indexName = ElasticSearchIndices.ES_INDEX_TROUBLES_COMPANY + "_" + entity.getCompanyId();
        //把单实例的Map变成每次调用都初始化,解决重新同步时需要重启服务器的问题。
        ConcurrentHashMap<String, IndexCoordinates> knownIndexCoordinates = new ConcurrentHashMap<>();
        return knownIndexCoordinates.computeIfAbsent(indexName, i -> {
            IndexCoordinates indexCoordinates = IndexCoordinates.of(i);
            IndexOperations indexOps = operations.indexOps(indexCoordinates);
            if (!indexOps.exists()) {
                indexOps.create();
                if (mapping == null) {
                    mapping = indexOps.createMapping(CompanyTroubleshootingBean.class);
                }
                indexOps.putMapping(mapping);
            }
            return indexCoordinates;
        });
    }
}

调用

do {
            IPage<CompanyTroubleshootingBean> beanPage = this.pageByCustom(new MyPage<>(index, 800), companyId);
            pages = beanPage.getPages();

            Iterable<CompanyTroubleshootingBean> saved = companyTroubleshootElasticRepository.save(beanPage.getRecords());
            if (saved != null && saved.iterator().hasNext()) {
                index++;
            } else {
                break;
            }

        } while (index <= pages);

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring BootElasticsearch整合是实现多版本兼容的一种常见方法。下面我将详细介绍这个方法。 1. 引入Elasticsearch依赖:在pom.xml文件中添加Elasticsearch的相关依赖,例如: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2. 配置Elasticsearch连接:在application.properties或application.yml文件中配置Elasticsearch的连接信息: ```properties spring.data.elasticsearch.cluster-nodes=localhost:9200 spring.data.elasticsearch.cluster-name=my-application ``` 3. 创建Elasticsearch Repository:创建一个继承自ElasticsearchRepository的接口,用于定义Elasticsearch的操作方法。例如: ```java @Repository public interface MyEntityRepository extends ElasticsearchRepository<MyEntity, String> { List<MyEntity> findByTitle(String title); } ``` 4. 创建实体类:创建一个与Elasticsearch索引对应的实体类,用于定义字段并与Elasticsearch的文档进行映射。例如: ```java @Document(indexName = "myindex", type = "myentity") public class MyEntity { @Id private String id; private String title; private String content; // 省略getter和setter方法 } ``` 5. 编写业务逻辑:在Service类中编写业务逻辑,通过调用Elasticsearch Repository的方法来实现Elasticsearch的操作,例如: ```java @Service public class MyEntityService { @Autowired private MyEntityRepository repository; public List<MyEntity> searchByTitle(String title) { return repository.findByTitle(title); } } ``` 通过上述步骤,我们可以基于Spring Boot快速构建与Elasticsearch的整合,并实现多版本兼容。包括以下几个关键点: - 使用Spring Boot的starter来简化配置和依赖管理。 - 引入Elasticsearch依赖来支持与Elasticsearch的连接和操作。 - 创建Elasticsearch Repository接口来定义Elasticsearch的操作方法。 - 创建实体类并进行与Elasticsearch的映射。 - 在Service类中编写业务逻辑,通过调用Elasticsearch Repository来实现Elasticsearch的操作。 这种方法可以在不同的Spring Boot版本之间实现兼容,使得开发者能够快速搭建基于Elasticsearch的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值