ElasticsearchTemplate实现ES读写操作

1 实现的读写操作

1.1 一般操作
package com.lenovo.qes.portal.modules.knowledge.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.lenovo.qes.portal.modules.knowledge.demo.document.ProductDocument;
import com.lenovo.qes.portal.modules.knowledge.demo.repository.ProductDocumentRepository;
import com.lenovo.qes.portal.modules.knowledge.demo.service.EsSearchService;
import com.lenovo.qes.portal.modules.knowledge.service.impl.BaseSearchServiceImpl;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * elasticsearch 搜索引擎 service实现
 * @author zhoudong
 * @version 0.1
 * @date 2018/12/13 15:33
 */
@Service
public class EsSearchServiceImpl extends BaseSearchServiceImpl<ProductDocument> implements EsSearchService {
    private Logger log = LoggerFactory.getLogger(getClass());
    @Resource
    private ElasticsearchTemplate elasticsearchTemplate;
    @Resource
    private ProductDocumentRepository productDocumentRepository;

    @Override
    public void save(ProductDocument ... productDocuments) {

		/**
		* 设置映射关系
		*/
        elasticsearchTemplate.putMapping(ProductDocument.class);
        if(productDocuments.length > 0){
            log.info("【保存索引】:{}",JSON.toJSONString(productDocumentRepository.saveAll(Arrays.asList(productDocuments))));
        }
    }

    /**
     * 按关键字搜索
     * @param keyword 关键字
     * @param clazz es文档映射的Java类型
     * @return 查询条件列表
     */
    @Override
    public List<T> query(String keyword, Class<T> clazz) {

		// 封装查询条件对象
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(new QueryStringQueryBuilder(keyword))
                .withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
                .withSort(new FieldSortBuilder("createTime").order(SortOrder.DESC))
                .build();

        return elasticsearchTemplate.queryForList(searchQuery,clazz);
    }

    /**
     * 搜索,命中关键字高亮,不分页
     * 
     * http://localhost:8080/query_hit?keyword=无印良品荣耀&indexName=orders&fields=productName,productDesc
     * @param keyword   关键字
     * @param indexName 索引库名称
     * @param fieldNames 搜索字段名称数组
     * @return 返回关键字对应的所有高亮的map数据
     */
    @Override
    public  List<Map<String,Object>> queryHit(String keyword,String indexName,String ... fieldNames) {
    
        // 构造查询条件,使用标准分词器.
        QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);

        // 设置高亮,使用默认的highlighter高亮器
        HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);

        // 设置查询字段
        SearchResponse response = elasticsearchTemplate
		        .getClient()
		        .prepareSearch(indexName)// 设置索引
                .setQuery(matchQuery)
                .highlighter(highlightBuilder)
                .setSize(10000) // 设置一次返回的文档数量,最大值:10000
                .get();

        // 返回搜索结果
        SearchHits hits = response.getHits();

        return getHitList(hits);
    }


    /**
     * 搜索高亮显示,然后分页返回
     * 
     * @param pageNo        当前页
     * @param pageSize      每页显示的总条数
     * @param keyword       关键字
     * @param indexName     索引库名称
     * @param fieldNames    搜索的字段数组
     * @return 返回关键字对应的所有高亮的map数据
     * @sample http://localhost:8080/query_hit_page?keyword=无印良品荣耀&indexName=orders&fields=productName,productDesc&pageNo=1&pageSize=1
     */
    @Override
    public Page<Map<String, Object>> queryHitByPage(int pageNo,int pageSize, String keyword, String indexName, String... fieldNames) {
        // 构造查询条件,使用标准分词器.
        QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);

        // 设置高亮,使用默认的highlighter高亮器
        HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);

        // 设置查询字段
        SearchResponse response = elasticsearchTemplate
		        .getClient()
		        .prepareSearch(indexName)
                .setQuery(matchQuery)
                .highlighter(highlightBuilder)
                .setFrom((pageNo-1) * pageSize)
                .setSize(pageNo * pageSize) // 设置一次返回的文档数量,最大值:10000
                .get();


        // 返回搜索结果
        SearchHits hits = response.getHits();

        Long totalCount = hits.getTotalHits();
        Page<Map<String, Object>> page = new Page<>(pageNo,pageSize,totalCount.intValue());
        page.setList(getHitList(hits));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteIndex(String indexName) {

		/**
		* 删除索引库
		*/
        elasticsearchTemplate.deleteIndex(indexName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(QesDocumentVo... qesDocumentVos) {

		// 初次保存的时候,设置映射类型。
        elasticsearchTemplate.putMapping(QesDocumentVo.class);
        if (qesDocumentVos.length > 0) {
            log.info("【保存索引】:{}", JSON.toJSONString(qesDocumentRepository.saveAll(Arrays.asList(qesDocumentVos))));
        }
    }

	/**
	* 根据文档id,所有文档删除
	* @param idList 文档ids
	*/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(List<String> idList) {
        
        if (CollectionUtils.isEmpty(idList)) {
            return;
        }
        
        // 构建es客户端
        String index = "qes";
        String type = "_doc";
        Client client = elasticsearchTemplate.getClient();
        
        // 构建批量删除请求对象
        BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
        for (String docId : idList) {
            DeleteRequestBuilder deleteRequestBuilder = client.prepareDelete(index, type, docId);
            bulkRequestBuilder.add(deleteRequestBuilder);
        }
        
        // 执行批量删除
        BulkResponse bulkResponse = bulkRequestBuilder.execute().actionGet();
        if (bulkResponse.hasFailures()) {
            log.error(bulkResponse.buildFailureMessage());
        }
    }




/*********************************私有方法************************************/
    /**
     * 处理高亮结果
     * @auther: zhoudong
     * @date: 2018/12/18 10:48
     */
    private List<Map<String,Object>> getHitList(SearchHits hits){
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map;
        for(SearchHit searchHit : hits){
            map = new HashMap<>(16);
            // 处理源数据
            map.put("source",searchHit.getSourceAsMap());
            // 处理高亮数据
            Map<String,Object> hitMap = new HashMap<>();
            searchHit.getHighlightFields().forEach((k,v) -> {
                StringBuilder hight = new StringBuilder();
                for(Text text : v.getFragments()) {
                    hight.append(text.string());
                }
                hitMap.put(v.getName(), hight.toString());
            });
            map.put("highlight",hitMap);
            list.add(map);
        }
        return list;
    }
}




1.2 其他操作
	/**
	* 根据ids,查询指定数量的文档
	*/
    @Override
    public List<QesDocumentVo> getDocumentByIdList(List<String> docIdList) {
        
        // 校验参数,并初始化数据
        List<QesDocumentVo> qesDocumentVoList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(docIdList)) {
            return qesDocumentVoList;
        }

		// 查询
        SearchResponse response = initBaseRequestBuilder()
                .setQuery(QueryBuilders.termsQuery("_id", docIdList))
                .setFrom(0)
                .setSize(1000)
                .get();
        
        // 解析结果
        SearchHits hits = response.getHits();
        
        // 返回数据
        if(hits.getTotalHits() <= 0) {
            return qesDocumentVoList;
        }
        
        return getHitList(hits);
    }

/**************************私有方法****************************/

    /**
     * 构建es查询请求对象
     * @auther: zhoudong
     * @date: 2018/12/18 10:48
     */
    private SearchRequestBuilder initBaseRequestBuilder(){
        String indexName = "qes";
        String[] includeFields = {"content", "meta.author", "meta.modifier", "file", "path"};
        return elasticsearchTemplate.getClient().prepareSearch(indexName)
                .setFetchSource(includeFields, null);
    }
    
    /**
     * 处理高亮结果
     * @auther: zhoudong
     * @date: 2018/12/18 10:48
     */
    private List<QesDocumentVo> getHitList(SearchHits hits){
        
        List<QesDocumentVo> list = Lists.newArrayList();
        if (hits == null || hits.getTotalHits() == 0) {
            return list;
        }
        
        for(SearchHit searchHit : hits){

			// convertEsDocument2QesDocumentVo string 转json装model,不赘述;
            list.add(convertEsDocument2QesDocumentVo(searchHit));
        }
        return list;
    }

2 使用的实体类

2.1 文档映射对象
package com.lenovo.qes.portal.modules.knowledge.Vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.elasticsearch.annotations.Document;

import java.io.Serializable;

/**
 * 产品实体
 * @author chenjun20
 * @version 0.1
 * @date 2020-03-25
 */
@Data
@Accessors(chain = true)
@ApiModel(value = "QesDocumentVo")
@Document(indexName = "qes", type = "_doc")
public class QesDocumentVo implements Serializable {
    @ApiModelProperty(value = "id")
    private String id;
    @ApiModelProperty(value = "文档id")
    private String docId;
    @ApiModelProperty(value = "文档内容")
    private String content;
    private KnowledgeDocPropertyVo knowledgeDocPropertyVo;
    private DocumentFileVo file;
    private DocumentMetaVo meta;
}
2.2 分页对象
/*
 * Copyright 2019-2029 geekidea(https://github.com/geekidea)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lenovo.qes.platform.common.vo;

import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

/**
 * @author geekidea
 * @date 2018-11-08
 */
@Data
@ApiModel("分页")
public class Paging<T> implements Serializable {
    private static final long serialVersionUID = -1683800405530086022L;

    @ApiModelProperty("总行数")
    @JSONField(name = "total")
    @JsonProperty("total")
    private long total = 0;

    @ApiModelProperty("数据列表")
    @JSONField(name = "records")
    @JsonProperty("records")
    private List<T> records = Collections.emptyList();

    public Paging() {
    }

    public Paging(IPage page) {
        this.total = page.getTotal();
        this.records = page.getRecords();
    }
    
    @Override
    public String toString() {
        return "Paging{" +
                "total=" + total +
                ", records=" + records +
                '}';
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Data Elasticsearch 中,可以使用 `ElasticsearchTemplate` 类进行 Elasticsearch 的插入操作。以下是使用 `ElasticsearchTemplate` 进行插入操作的示例代码: 1. 添加 Elasticsearch 相关依赖:在您的项目的构建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)中,添加适用于 Elasticsearch 的 Spring Data Elasticsearch 依赖。例如,对于 Maven,您可以添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2. 创建实体类:创建一个用于映射 Elasticsearch 文档的实体类。例如: ```java import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "my_index", type = "my_type") public class MyEntity { @Id private String id; private String field1; private String field2; // getter and setter methods } ``` 3. 插入操作代码:使用 `ElasticsearchTemplate` 进行插入操作。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.stereotype.Service; @Service public class MyEntityService { @Autowired private ElasticsearchTemplate elasticsearchTemplate; public void saveEntity(MyEntity entity) { elasticsearchTemplate.index(entity); elasticsearchTemplate.refresh(MyEntity.class); } } ``` 4. 调用插入方法:在您的代码中,创建一个 `MyEntity` 对象,设置相应的字段值,然后调用 `saveEntity` 方法进行插入操作。例如: ```java MyEntity entity = new MyEntity(); entity.setId("1"); entity.setField1("value1"); entity.setField2("value2"); myEntityService.saveEntity(entity); ``` 通过以上步骤,您可以使用 `ElasticsearchTemplate` 进行 Elasticsearch 的插入操作。请根据实际需求进行相应的调整和扩展。请注意,`ElasticsearchTemplate` 在 Spring Data Elasticsearch 4.x 版本中已被弃用,建议使用 `ElasticsearchRepository` 进行数据操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值