java整合Elasticsearch,实现crud以及高级查询的分页,范围,排序功能,泰文分词器的使用,分组,最大,最小,平均值,以及自动补全功能

//为index创建mapping,index相当于mysql的数据库,数据库里的表也要给各个字段创建类型,所以index也要给字段事先设置好类型:

使用postMan或者其他工具创建:(此处我使用postMan,创建一个名为shop的index,type是order-- type相等于mysql的表)

//这里的背景是一个订单表对应多个订单项表(商品信息),然后就将所有的订单和购买的商品信息存到ES,我这里的ES版本是6.4.2

//以下介绍的mapping字段分词器都是英文的,如果要使用中文分词器,就自行百度es如何配置中文分词器

put localthost:9200/shop

{
"mappings": {
"order": {
"dynamic": false,//设置为false的意思就是以后不能动态添加字段
"properties": {
"orderId": {
"type": "keyword", // 字符串类型只有textkeyword,text是会分词
"index": true //如果要以该字段作为搜索条件,就必须写成true
},
"orderAmount": {
"type": "double"
},
"orderTitle": {
"type": "text",
"analyzer": "english" //英文分词器,如果使用中文ik分词器,就自行百度怎么配置
},
"customerId": {
"type": "keyword",
"index": true
},
"orderSubmit": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"payTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"finshiTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"expressAmount": {
"type": "double"
},
"deliveryTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"couponAmount": {
"type": "double"
},
"score": {
"type": "integer"
},
"scoreAmount": {
"type": "double"
},
"orderStatus": {
"type": "integer"
},
"paymentStatus": {
"type": "integer"
},
"markertId": {
"type": "keyword",
"index": true
},
"shopId": {
"type": "keyword",
"index": true
},
"shopName": {
"type": "text",
"analyzer": "english"
},
"address": {
"type": "text",
"analyzer": "standard"
},
"recieveName": {
"type": "text",
"analyzer": "standard"
},
"phone": {
"type": "keyword",
"index": true
},
"itemList": {
"properties": {
"orderItemId": {
"type": "keyword",
"index": true
},
"itemId": {
"type": "keyword",
"index": true
},
"itemTitle": {
"type": "text",
"analyzer": "english"
},
"itemType": {
"type": "integer"
},
"quanity": {
"type": "integer"
},
"price": {
"type": "double"
},
"totalAmount": {
"type": "double"
}
}
}
}
}
}
}
//创建完成后,使用es可视化工具(我使用的是head)在浏览器登录可以看到对应的shop索引了

//ES的order对象结构如下:

public class EsOrderMast {
    private String orderId;
    private BigDecimal orderAmount;
    private String orderTitle;
    private String customerId;
    private String  orderSubmit;
    private String  payTime;
    private String finshiTime;
    private BigDecimal expressAmount;
    private String deliveryTime;
    private BigDecimal couponAmount;
    private Integer score;
    private BigDecimal scoreAmount;
    private Integer orderStatus;
    private Integer paymentStatus;
    private String markertId;
    private String shopId;
    private String shopName;
    private String address;
    private String recieveName;
    private String phone;
    private List<EsOrderItem> itemList=new ArrayList<>();//订单的商品信息
}//省略了setter和getter

 //订单的商品ES对象结构:

public class EsOrderItem {

    private String orderItemId;

    private String itemId;

    private String itemTitle;

    private Integer itemType;

    private Integer quanity;

    private BigDecimal price;

    private BigDecimal totalAmount;
}//省略setter和getter

//第一步创建java客户端,下面的例子都是通过该Util获取客户端client对象,当然也可以通过配置方式然后注入

public abstract class ESUtil {

    private static TransportClient client = null;



    public static TransportClient getClient()  {
        if(client==null){
            Settings settings = Settings.builder().put("cluster.name", "yangxiaohui").build();//集群名称在es的配置文件可以找到
            try {
                client = new PreBuiltTransportClient(settings).addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        return client;
    }

}

//springboot整合es,使用时就可以通过Autowired注入的方式获取client对象,之后的例子获取客户端还是以EsUtil类获取,这里为了技术完整性附加上:

package com.example.demo.domain;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.net.InetAddress;

@Configuration
public class ElasticsearchConfig  implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchConfig.class);

    @Value("${tc.elasticsearch.cluster.name}")
    private String clusterName;

    @Value("${tc.elasticsearch.port}")
    private Integer port;

    @Value("${tc.elasticsearch.ip}")
    private String host;
    
    /**
     * Springboot整合Elasticsearch 在项目启动前设置一下的属性,防止报错
     * 解决netty冲突后初始化client时还会抛出异常
     * java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]
     */
    @PostConstruct
   void init() {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }


    @Bean
    public TransportClient getTransportClient() {
        TransportClient client=null;
        LOGGER.info("elasticsearch init.");
        try {
            Settings settings = Settings.builder()
                    .put("cluster.name", clusterName) //集群名字
                    .put("client.transport.sniff", true)//增加嗅探机制,找到ES集群
                    .put("thread_pool.search.size", 5).build();//增加线程池个数
            client = new PreBuiltTransportClient(settings);
            TransportAddress transportAddress = new TransportAddress(InetAddress.getByName(host), port);
            client.addTransportAddresses(transportAddress);
            LOGGER.info("elasticsearch init success.");
            return client;
        } catch (Exception e) {
            throw new RuntimeException("elasticsearch init fail."+ e);
        }
    }
    
    

    public String getClusterName() {
        return clusterName;
    }

    public void setClusterName(String clusterName) {
        this.clusterName = clusterName;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }


    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

//将数据库的信息查询出来,然后批量初始化到ES中

//批量新增
    @Async //异步方式
    public void initESOrderMast() {
        List<EsOrderMast> esItemList = orderMastMapper.findEsItemList();
        TransportClient client = ESUtil.getClient();
        BulkRequest bulkRequest = new BulkRequest();
        if(null!=esItemList && esItemList.size()>0){
            for (EsOrderMast esOrderMast : esItemList) {
                IndexRequest indexRequest = new IndexRequest("shop", "order", esOrderMast.getOrderId());
                indexRequest.source(JSON.toJSONString(esOrderMast), XContentType.JSON);
                bulkRequest.add(indexRequest);
            }
        }
        ActionFuture<BulkResponse> bulk = client.bulk(bulkRequest);
        System.out.println(bulk.isDone());
        BulkResponse bulkItemResponses = bulk.actionGet();
        System.out.println(bulkItemResponses.status().getStatus());

    }

//下面是增删改查代码

 //删除
    public boolean deleteByOrderId(String orderId){
        boolean flag =false;
        TransportClient client = ESUtil.getClient();
        ActionFuture<DeleteResponse> actionFuture = client.delete(new DeleteRequest("shop", "order", orderId));
        flag = actionFuture.isDone();
        DeleteResponse deleteResponse = actionFuture.actionGet();
        System.out.println(deleteResponse.getResult().toString());
        System.out.println(deleteResponse.status().getStatus());
        return flag;
    }
    //查找
    public EsOrderMast getOrderByOrderId(String orderId){
        EsOrderMast esOrderMast=null;
        TransportClient client = ESUtil.getClient();
        GetRequestBuilder getRequestBuilder = client.prepareGet("shop", "order", orderId);
        GetResponse response = getRequestBuilder.get();
        String sourceAsString = response.getSourceAsString();
        esOrderMast = JSON.parseObject(sourceAsString, EsOrderMast.class);
        return esOrderMast;
    }
    //修改
    public boolean update(String orderId,Integer orderStatus) {
        EsOrderMast orderMast = getOrderByOrderId(orderId);
        orderMast.setOrderStatus(orderStatus);
        orderMast.setFinshiTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        TransportClient client = ESUtil.getClient();
        //UpdateResponse updateResponse = client.prepareUpdate("shopdb", "order", orderId).setDoc(JSON.toJSONString(orderMast), XContentType.JSON).execute().actionGet();
       /* UpdateRequest request = new UpdateRequest("", "order", orderId);
        request.doc(JSON.toJSON(orderMast),XContentType.JSON);*/


        //client.update(request).get();
        UpdateResponse updateResponse = client.prepareUpdate("shop", "order", orderId)
                .setDoc(JSON.toJSON(orderMast),XContentType.JSON).get();
        //System.out.println(update.actionGet().status().getStatus());

        return updateResponse.status().getStatus()==200?true:false;


    }

//高级查询:分页,排序,范围查找:

先看高级查询请求对象:

public class EsQueryObject {
    private String orderId;

    private String customerId;

    private String txtOrderTitle;

    private Integer orderStatus;

    private Integer paymentStatus;

    private String phone;

    private String recieveName;

    private String addresss;

    private String orderSubmitTime_S;
    private String orderSubmitTime_E;

    private String payTime_S;
    private String payTime_E;

    private BigDecimal minPayAmount;

    private BigDecimal maxPayAmount;

    private String shopId;

    private String itemId;

    private String itemTile;

    private Page page;
}

//高级查询方法:(es的分页默认从0开始,如果没有设置分页,或者没有设置每页大小,默认返回10条数据)


public List<EsOrderMast> findOrderList(EsQueryObject queryObject){
TransportClient client = ESUtil.getClient();
SearchRequestBuilder sourceBuilder=client.prepareSearch("shop");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if(!StringUtils.isEmpty(queryObject.getOrderId())){
boolQueryBuilder.must(QueryBuilders.termQuery("orderId",queryObject.getOrderId()));
}
if(!StringUtils.isEmpty(queryObject.getCustomerId())){
boolQueryBuilder.must(QueryBuilders.termQuery("customerId",queryObject.getCustomerId()));
}
if(!StringUtils.isEmpty(queryObject.getTxtOrderTitle())){
boolQueryBuilder.must(QueryBuilders.matchQuery("orderTitle",queryObject.getTxtOrderTitle()));
}

if(null!=queryObject.getOrderStatus() && queryObject.getOrderStatus()>=0){
boolQueryBuilder.must(QueryBuilders.termQuery("orderStatus",queryObject.getOrderStatus()));
}
if(null!=queryObject.getPaymentStatus() && queryObject.getPaymentStatus()>=0){
boolQueryBuilder.must(QueryBuilders.termQuery("paymentStatus",queryObject.getPaymentStatus()));
}
if(!StringUtils.isEmpty(queryObject.getPhone())){
boolQueryBuilder.must(QueryBuilders.termQuery("phone",queryObject.getPhone()));
}
if(!StringUtils.isEmpty(queryObject.getRecieveName())){
boolQueryBuilder.must(QueryBuilders.matchQuery("recieveName",queryObject.getRecieveName()));
}
if(!StringUtils.isEmpty(queryObject.getAddresss())){
boolQueryBuilder.must(QueryBuilders.matchQuery("addresss",queryObject.getAddresss()));
}

if(!StringUtils.isEmpty(queryObject.getShopId())){
boolQueryBuilder.must(QueryBuilders.termQuery("shopId",queryObject.getShopId()));
}
if(!StringUtils.isEmpty(queryObject.getItemId())){
boolQueryBuilder.must(QueryBuilders.termQuery("itemList.itemId",queryObject.getItemId()));
}
if(!StringUtils.isEmpty(queryObject.getItemTile())){
boolQueryBuilder.must(QueryBuilders.matchQuery("itemList.itemTitle",queryObject.getItemTile()));
}


if(!StringUtils.isEmpty(queryObject.getOrderSubmitTime_S())){
boolQueryBuilder.must(QueryBuilders.rangeQuery("orderSubmit").gte(queryObject.getOrderSubmitTime_S()));
}
if(!StringUtils.isEmpty(queryObject.getOrderSubmitTime_E())){
boolQueryBuilder.must(QueryBuilders.rangeQuery("orderSubmit").lte(queryObject.getOrderSubmitTime_E()));
}
if(!StringUtils.isEmpty(queryObject.getPayTime_S())){
boolQueryBuilder.must(QueryBuilders.rangeQuery("payTime").gte(queryObject.getPayTime_S()));
}
if(!StringUtils.isEmpty(queryObject.getPayTime_E())){
boolQueryBuilder.must(QueryBuilders.rangeQuery("payTime").lte(queryObject.getPayTime_E()));
}

if(null!=queryObject.getMinPayAmount()){
boolQueryBuilder.must(QueryBuilders.rangeQuery("orderAmount").gte(queryObject.getMinPayAmount().doubleValue()));
}
if(null!=queryObject.getMaxPayAmount()){
boolQueryBuilder.must(QueryBuilders.rangeQuery("orderAmount").lte(queryObject.getMaxPayAmount().doubleValue()));
}
sourceBuilder.setQuery(boolQueryBuilder);
sourceBuilder.addSort(SortBuilders.fieldSort("orderSubmit").order(SortOrder.ASC));//排序
/*
//有时想每个分组取一条数据,这样可以使用下面的方法
CollapseBuilder groupShopId = new CollapseBuilder("shopId"); //表示按shopId进行分组,然后去重,每组取一条
sourceBuilder.setCollapse(groupShopId);
CardinalityAggregationBuilder cab=AggregationBuilders.cardinality("group_count").field("shopId");//获取分组的组数,因为通过下面
hits.totalHits获取的总数不是分组的总数,这里可以统计分组的组数,在分页时可以有用
sourceBuilder.addAggregation(cab);*/
if(null!=queryObject.getPage()){
Page page = queryObject.getPage();
int pageSize = page.getPageSize()==0?10:page.getPageSize();
    //分页中的setFrom是偏移量不是当前页数
sourceBuilder.setFrom((page.getPageNum() == 0 ? 0 : page.getPageNum() - 1) * page.getPageSize()).setSize(pageSize);

}
List<EsOrderMast> list = new ArrayList<>();
ActionFuture<SearchResponse> execute = sourceBuilder.execute();
SearchResponse searchResponse = null;
try {
searchResponse = execute.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// Aggregation group_count = searchResponse.getAggregations().get("group_count"); //打印分组的组数
//System.out.println(group_count.toString());

SearchHits hits = searchResponse.getHits();
System.out.println(searchResponse.getHits().totalHits);
if(null!=hits && hits.totalHits>0) {
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
EsOrderMast orderMast = JSON.parseObject(sourceAsString, EsOrderMast.class);
list.add(orderMast);
}
}
return list;


}
 

//附上maven

<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.4.2</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency>
//自定义分词器,如这里是泰文分词器:
{
"settings": {
"analysis": {
"analyzer": {
"thai_analyzer": { //自定义分词器名称
"type": "custom",
"tokenizer": "thai", //es自带thai文分词器,不用下载
"filter": [
"lowercase",
"asciifolding"
]
},
"caseSensitive": { //设置大小写是否敏感,对于部分词的字段大小写需要敏感
"filter": "lowercase",
"type": "custom",
"tokenizer": "keyword"
}
}
}
},
"mappings": {
"order": {
"dynamic": false,
"properties": {
"orderId": {
"type": "keyword",
"index": true
},
"orderAmount": {
"type": "double"
},
"orderTitle": {
"type": "text",
"analyzer": "thai_analyzer", //创建文档时使用泰文自定义分词器
"search_analyzer": "thai_analyzer" //查询时使用泰文分词器
},
"customerId": {
"type": "keyword",
"index": true
},
"orderSubmit": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"payTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"finshiTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"expressAmount": {
"type": "double"
},
"deliveryTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
},
"couponAmount": {
"type": "double"
},
"score": {
"type": "integer"
},
"scoreAmount": {
"type": "double"
},
"orderStatus": {
"type": "integer"
},
"paymentStatus": {
"type": "integer"
},
"markertId": {
"type": "keyword",
"index": true
},
"shopId": {
"type": "keyword",
"index": true
},
"shopName": {
"type": "text",
"analyzer": "thai_analyzer",
"search_analyzer": "thai_analyzer"
},
"address": {
"type": "text",
"analyzer": "thai_analyzer",
"search_analyzer": "thai_analyzer"
},
"recieveName": {
"type": "text",
"analyzer": "thai_analyzer",
"search_analyzer": "thai_analyzer"
},
"phone": {
"type": "keyword",
"index": true
},
"itemList": {
"properties": {
"orderItemId": {
"type": "keyword",
"index": true
},
"itemId": {
"type": "keyword",
"index": true
},
"itemTitle": {
"type": "text",
"analyzer": "thai_analyzer",
"search_analyzer": "thai_analyzer"
},
"itemType": {
"type": "integer"
},
"quanity": {
"type": "integer"
},
"price": {
"type": "double"
},
"totalAmount": {
"type": "double"
}
}
}
}
}
}
}
//聚合查询:分组,求最大,最小,平均值:
对一个数据集求最大、最小、和、平均值等指标的聚合,在ES中称为指标聚合(Metrics(指标))
Buckets(桶/集合):满足特定条件的文档的集合
 public List<EsOrderMast> aggs(EsQueryObject queryObject) throws ExecutionException, InterruptedException {
        TransportClient client = ESUtil.getClient();
        SearchRequestBuilder sourceBuilder=client.prepareSearch("shop");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(!StringUtils.isEmpty(queryObject.getOrderId())){
            boolQueryBuilder.must(QueryBuilders.termQuery("orderId",queryObject.getOrderId()));
        }
        if(!StringUtils.isEmpty(queryObject.getCustomerId())){
            boolQueryBuilder.must(QueryBuilders.termQuery("customerId",queryObject.getCustomerId()));
        }
        if(!StringUtils.isEmpty(queryObject.getTxtOrderTitle())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("orderTitle",queryObject.getTxtOrderTitle()));
        }

        if(null!=queryObject.getOrderStatus() && queryObject.getOrderStatus()>=0){
            boolQueryBuilder.must(QueryBuilders.termQuery("orderStatus",queryObject.getOrderStatus()));
        }
        if(null!=queryObject.getPaymentStatus() && queryObject.getPaymentStatus()>=0){
            boolQueryBuilder.must(QueryBuilders.termQuery("paymentStatus",queryObject.getPaymentStatus()));
        }
        if(!StringUtils.isEmpty(queryObject.getPhone())){
            boolQueryBuilder.must(QueryBuilders.termQuery("phone",queryObject.getPhone()));
        }
        if(!StringUtils.isEmpty(queryObject.getRecieveName())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("recieveName",queryObject.getRecieveName()));
        }
        if(!StringUtils.isEmpty(queryObject.getAddresss())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("addresss",queryObject.getAddresss()));
        }

        if(!StringUtils.isEmpty(queryObject.getShopId())){
            boolQueryBuilder.must(QueryBuilders.termQuery("shopId",queryObject.getShopId()));
        }
        if(!StringUtils.isEmpty(queryObject.getItemId())){
            boolQueryBuilder.must(QueryBuilders.termQuery("itemList.itemId",queryObject.getItemId()));
        }
        if(!StringUtils.isEmpty(queryObject.getItemTile())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("itemList.itemTitle",queryObject.getItemTile()));
        }


        if(!StringUtils.isEmpty(queryObject.getOrderSubmitTime_S())){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("orderSubmit").gte(queryObject.getOrderSubmitTime_S()));
        }
        if(!StringUtils.isEmpty(queryObject.getOrderSubmitTime_E())){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("orderSubmit").lte(queryObject.getOrderSubmitTime_E()));
        }
        if(!StringUtils.isEmpty(queryObject.getPayTime_S())){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("payTime").gte(queryObject.getPayTime_S()));
        }
        if(!StringUtils.isEmpty(queryObject.getPayTime_E())){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("payTime").lte(queryObject.getPayTime_E()));
        }

        if(null!=queryObject.getMinPayAmount()){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("orderAmount").gte(queryObject.getMinPayAmount().doubleValue()));
        }
        if(null!=queryObject.getMaxPayAmount()){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("orderAmount").lte(queryObject.getMaxPayAmount().doubleValue()));
        }
        sourceBuilder.setQuery(boolQueryBuilder);
        /*sourceBuilder.addSort(SortBuilders.fieldSort("orderSubmit").order(SortOrder.ASC));//排序
        sourceBuilder.addAggregation(AggregationBuilders.max("max").field("orderAmount"));//最大值
        sourceBuilder.addAggregation(AggregationBuilders.min("min").field("orderAmount")); //最小值
        sourceBuilder.addAggregation(AggregationBuilders.count("total").field("orderId")); //总数
        sourceBuilder.addAggregation(AggregationBuilders.sum("totalAmount").field("orderAmount"));//总金额
        sourceBuilder.addAggregation(AggregationBuilders.avg("avg").field("orderAmount"));//平均金额*/
        sourceBuilder.setSize(0);//设置为0就不用返回结果集,这样性能更高
        //按商家分组再统计
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("shops").field("shopId").subAggregation(AggregationBuilders.max("max").field("orderAmount"))
                .subAggregation(AggregationBuilders.avg("avg").field("orderAmount"));
        sourceBuilder.addAggregation(termsAggregationBuilder);
        ActionFuture<SearchResponse> execute = sourceBuilder.execute();
        SearchResponse searchResponse = execute.get();
        //Aggregation max = searchResponse.getAggregations().get("max");
       // Aggregation min = searchResponse.getAggregations().get("min");
        //Aggregation total = searchResponse.getAggregations().get("total");
        //Aggregation totalAmount = searchResponse.getAggregations().get("totalAmount");
        //System.out.println(max.toString());
       // System.out.println(min.toString());
        //System.out.println(total.toString());
       // System.out.println(totalAmount.toString());
        Aggregation shops = searchResponse.getAggregations().get("shops");
        System.out.println(shops.toString());
        //如果你要在商家分组之后继续分组,那只要加个subAggregation(AggregationBuilders.terms("xx").field("xx"))


        return null;


    }
//聚合如果报错,分组的字段要在,mapping中设置fildData属性为true,这里以商家名称
如:
     "shopName": {
"type": "keyword",
"index": true,
      "fielddata": true
}

官方文档介绍,type类型为text时,并且需要该字段进行分组时需要设置:
Fielddata is disabled on text fields by default. Set fielddata=true on [your_field_name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.

//自动补全介绍:在百度搜索时,经常会有自动补全功能,下面我以商品的标题作为补全字段
//将mysql商品表所有的商品标题存到ES中
//第一步创建mapping:
localhost:9200/shop_sugess

{

   "mappings": {
      "suggest": {
        "properties": {
          "titleSugess": {
            "type": "completion",
            "analyzer": "english",
            "search_analyzer": "english"
          }
        }
      }
   }
}
//第二步初始化数据进es:
//批量新增
@Async
public void initSugess() throws IOException {
List<String> titleList = orderItemMapper.findItemTitleList();
TransportClient client = ESUtil.getClient();
BulkRequest bulkRequest = new BulkRequest();
if(null!=titleList && titleList.size()>0){
for (String title : titleList) {
IndexRequest indexRequest = new IndexRequest("shop_sugess", "suggest");
XContentBuilder endObject = XContentFactory.jsonBuilder().startObject()
.field("titleSugess",title)
.endObject();
indexRequest.source(endObject);
bulkRequest.add(indexRequest);
}
}
ActionFuture<BulkResponse> bulk = client.bulk(bulkRequest);
System.out.println(bulk.isDone());
BulkResponse bulkItemResponses = bulk.actionGet();
System.out.println(bulkItemResponses.status().getStatus());

}


//第三步开始查询:
//查询
public void testSugess(String prexfit){
String suggestField="title_suggest";//指定在哪个字段搜索
Integer suggestMaxCount=10;//获得最大suggest条数
CompletionSuggestionBuilder suggestionBuilderDistrict = new CompletionSuggestionBuilder("titleSugess").prefix(prexfit).size(suggestMaxCount);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("my_suggest", suggestionBuilderDistrict);//添加suggest
TransportClient client = ESUtil.getClient();
SearchRequestBuilder requestBuilder =client.prepareSearch("shop_sugess").setTypes("suggest").suggest(suggestBuilder);
SearchResponse response = requestBuilder.get();
Suggest suggest = response.getSuggest();
Iterator<Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>> iterator = suggest.iterator();
while (iterator.hasNext()){
Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> next = iterator.next();
List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries = next.getEntries();
for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : entries) {
List<? extends Suggest.Suggestion.Entry.Option> options = entry.getOptions();
for (Suggest.Suggestion.Entry.Option option : options) {
System.out.println(option.getText().toString());
}
}
}

}
//此处以Sam作为前缀查询:结果如下

 

 //es批量新增的其他方式:

 //批量新增
    public void batchInsertHotWordSuggest(List<HotWorderSuggestDTO> list) {
        if(CommonUtil.isNull(list)){
            return;
        }
        BulkRequest bulkRequest = new BulkRequest();
        list.stream().forEach(a->{
            IndexRequest indexRequest = new IndexRequest(SUGGEST_INDEX_NAME, SUGGEST_TYPE_NAME, a.getId());

            XContentBuilder suggestDTO = null;
            try {
                suggestDTO = XContentFactory.jsonBuilder()
                        .startObject()
                        .field("title_suggest", a.getTitle_suggest())
                        .endObject();
            } catch (IOException e) {
               logger.info("热搜词同步失败...."+e.getMessage()+a.getTitle_suggest());
            }
            if(null!=suggestDTO){
                indexRequest.source(suggestDTO);
                bulkRequest.add(indexRequest);
            }
        });
        ActionFuture<BulkResponse> bulk = client.bulk(bulkRequest);
        if(null!=bulk.actionGet() && null!=bulk.actionGet().status() && bulk.actionGet().status().getStatus()!=200){
            logger.info("批量同步搜索词失败");
        }

    }
public List<String> findShopItemList(RequestDTO requestDTO, Page page) {

		SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
		searchRequest.types(TYPE_NAME);
		// 构造查询器
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

		//品牌
		if (StringUtils.isNotBlank(requestDTO.getBrandId())) {
			boolQueryBuilder.must(QueryBuilders.termsQuery("brandId", requestDTO.getBrandId()));
		}
		//分类
		if (StringUtils.isNotBlank(requestDTO.getCategoryId())) {//前缀查询
			boolQueryBuilder.must(QueryBuilders.prefixQuery("classId", requestDTO.getCategoryId()));
		}

        boolQueryBuilder.must(QueryBuilders.termQuery("flgItemOnline", ItemTypeEnum.FLG_ITEM_TYPE_ONE.getValue().toString()));
		//or查询
		boolQueryBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.termQuery("bolStock", "y")).should(QueryBuilders.termQuery("bolOverdue", "y")));
		boolQueryBuilder.must(QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("datSellStart").lte(DateUtil.getTime())).must(QueryBuilders.rangeQuery("datSellEnd").gte(DateUtil.getTime())));
		sourceBuilder.query(boolQueryBuilder);
		sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        if(null==page){
            page=new Page(1,10);
        }
        if(page.getPageSize()<=0){
            page.setPageSize(10);
        }

        sourceBuilder.from((page.getPageNum() == 0 ? 0 : page.getPageNum() - 1) * page.getPageSize());
        sourceBuilder.size(page.getPageSize());
        Integer sortPrice = requestDTO.getSortPrice();
        Integer sortSale = requestDTO.getSortSale();
        if(null!=sortSale && sortSale>0 ){// "排序(0,不排序 1.降序 2.升序)
            sourceBuilder.sort(new FieldSortBuilder("sellTotal").order(sortSale==1?SortOrder.DESC:SortOrder.ASC));
        }
        if(null!=sortPrice && sortPrice>0 ) {// 排序排行(0,不排序 1.降序 2.升序)
            sourceBuilder.sort(new FieldSortBuilder("price").order(sortSale == 1 ? SortOrder.DESC : SortOrder.ASC));
        }

		searchRequest.source(sourceBuilder);
		searchRequest.searchType(SearchType.QUERY_THEN_FETCH);
		SearchResponse searchResponse = client.search(searchRequest).actionGet();

        if(null==searchResponse || null==searchResponse.getHits() || searchResponse.getHits().totalHits<=0){
            return null;
        }
        List<String> list = new ArrayList<>();
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> hitMap = hit.getSourceAsMap();
            if (null != hitMap) {
                String itemId = (String) hitMap.get("itemId");
                list.add(itemId);
            }
        }
        return list;
    }




原文地址:https://www.cnblogs.com/yangxiaohui227/p/11237268.html