Elasticsearch

一捺氢、簡介安裝

官方網(wǎng)址:https://www.elastic.co/cn/
安裝elasticsearch:下載并解壓
安裝kibana:下載并解壓
下載ik分詞器:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v8.2.0

1、適配kibana中kibana.yml文件
elasticsearch.hosts: ["http://localhost:9200"]
2、解壓ik分詞器包放在elasticsearch的plugins的新建ik文件夾下
官方網(wǎng)址:https://www.elastic.co/cn/
3挽唉、操作網(wǎng)址:http://localhost:5601/app/dev_tools#/console

二、ik分詞解析器

1朵锣、分詞最少切分
POST /_analyze
{
    "text": "河馬生鮮,阿里巴巴出品",
    "analyzer": "ik_smart"
}
2、分詞最細(xì)切分
POST /_analyze
{
    "text": "河馬生鮮火邓,阿里巴巴出品",
    "analyzer": "ik_max_word"
}
3、擴(kuò)展ik分詞器

在IKAnalyzer.xml文件中設(shè)置擴(kuò)展配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 擴(kuò)展配置</comment>
    <!--用戶可以在這里配置自己的擴(kuò)展字典 -->
    <entry key="ext_dict">ext.dic</entry>
     <!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
    <entry key="ext_stopwords">stopword.dic</entry>
    <!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展停止詞字典-->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

在ext.dic塑顺、stopword.dic文件中添加詞匯

三须误、操作索引庫

1、mapping常見屬性

type:數(shù)據(jù)類型(是否參與搜索)
index:是否索引
analyzer:分詞器
properties:子字段

2旭绒、創(chuàng)建索引庫(spring索引庫名稱)
PUT /spring
{
  "mappings": {
    "properties": {
      "info": {
        "analyzer": "ik_smart", 
        "type": "text"
      },
      "email":{
        "type": "keyword",
        "index": false
      },
      "name":{
        "type": "object",
        "properties": {
          "lastName": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
3鸟妙、查詢索引庫
GET /spring
4焦人、刪除索引庫
DELETE /spring
5、修改索引庫
PUT /spring/_mapping
{
  "properties": {
    "新字段名": {
      "type": "keyword"
      "index": false
    }
  }
}

四圆仔、操作文檔

1垃瞧、插入文檔(spring索引庫名稱,1文檔id)
POST /spring/_doc/1
{
  "info": "文本內(nèi)容分詞",
  "email": "123456@163.com",
  "name": {
    "lastName": "趙"
  }
}
2坪郭、查詢文檔
GET /spring/_doc/1
3个从、刪除文檔
DELETE /spring/_doc/1
4、全量修改
PUT /spring/_doc/1
{
  "info": "阿里巴巴出品歪沃,等于白嫖了嗦锐,真的是奧利給",
  "email": "ALIBB@COM",
  "name": {
    "lastName": "趙"
  }
}
5、局部修改
POST /spring/_update/1
{
  "doc": {
    "email": "alibaba@ali.cn"
  }
}

五沪曙、代碼操作ES(RestClient)

1奕污、官方文檔地址

https://www.elastic.co/guide/en/elasticsearch/client/index.html
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

2、mapping映射字符串
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "address": {
        "type": "keyword",
        "index": false
      },
      "price": {
        "type": "integer"
      },
      "score": {
        "type": "integer"
      },
      "brand": {
        "type": "keyword",
        "copy_to": "name"
      },
      "city": {
        "type": "keyword"
      },
      "starName": {
        "type": "keyword"
      },
      "business": {
        "type": "keyword",
        "copy_to": "name"
      },
      "location": {
        "type": "geo_point"
      },
      "pic": {
        "type": "keyword",
        "index": false
      }
    }
  }
}
3液走、在pom文件中引入
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
4碳默、索引庫操作
public class HotelIndexTest {
    
    private RestHighLevelClient restHighLevelClient;

    @Test
    void createHotelIndex() throws IOException {
        //創(chuàng)建Request對(duì)象
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        //DSL語句
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        //發(fā)送請(qǐng)求
        restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
    }

    //刪除索引庫
    @Test
    void deleteHotelIndex() throws IOException {
        //創(chuàng)建Request對(duì)象
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        //發(fā)送請(qǐng)求
        restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
    }

    //索引庫是否存在
    @Test
    void existsHotelIndex() throws IOException {
        //創(chuàng)建Request對(duì)象
        GetIndexRequest request = new GetIndexRequest("hotel");
        //發(fā)送請(qǐng)求
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    }

    @BeforeEach
    void setUp() {
        this.restHighLevelClient = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://localhost:9200")));
    }

    @AfterEach
    void tearDown() throws IOException {
        restHighLevelClient.close();
    }
}

設(shè)置MAPPING_TEMPLATE常量

public class HotelConstants {
    public static final String MAPPING_TEMPLATE = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"address\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"price\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"brand\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"city\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"starName\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"location\": {\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \"pic\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"all\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}
5、文檔操作
@SpringBootTest
public class HotelDocumentTest {

    @Autowired
    private IHotelService hotelService;

    private RestHighLevelClient client;

    //插入文檔數(shù)據(jù)
    @Test
    public void testAddDocument() throws IOException {
        //根據(jù)ID查詢酒店數(shù)據(jù)
        Hotel hotel = hotelService.getById(38665L);
        //轉(zhuǎn)換為文檔類型
        HotelDoc hotelDoc = new HotelDoc(hotel);
        //創(chuàng)建Request對(duì)象
        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        //準(zhǔn)備json文檔
        request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        //發(fā)送請(qǐng)求
        client.index(request, RequestOptions.DEFAULT);
    }

    //獲取文檔數(shù)據(jù)
    @Test
    public void testGetDocumentById() throws IOException {
        //創(chuàng)建Request對(duì)象
        GetRequest request = new GetRequest("hotel", "61083");
        //發(fā)送請(qǐng)求
        GetResponse documentFields = client.get(request, RequestOptions.DEFAULT);
        String sourceAsString = documentFields.getSourceAsString();
        HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
    }

    //更新文檔
    @Test
    public void testUpdateDocumentById() throws IOException {
        //創(chuàng)建Request對(duì)象
        UpdateRequest request = new UpdateRequest("hotel", "61083");
        request.doc("price",888);
        //發(fā)送請(qǐng)求
        client.update(request, RequestOptions.DEFAULT);
    }

    //刪除文檔
    @Test
    public void testDeleteDocumentById() throws IOException {
        //創(chuàng)建Request對(duì)象
        DeleteRequest request = new DeleteRequest("hotel", "61083");
        //發(fā)送請(qǐng)求
        client.delete(request, RequestOptions.DEFAULT);
    }

    //批量導(dǎo)入
    @Test
    public void testBulk() throws IOException {
        //根據(jù)ID查詢酒店數(shù)據(jù)
        List<Hotel> list = hotelService.list();
        //創(chuàng)建Request對(duì)象
        BulkRequest request = new BulkRequest();
        for (Hotel hotel : list) {
            //轉(zhuǎn)換為文檔類型
            HotelDoc hotelDoc = new HotelDoc(hotel);
            request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));
        }
        //發(fā)送請(qǐng)求
        client.bulk(request, RequestOptions.DEFAULT);
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://localhost:9200")));
    }

    @AfterEach
    void tearDown() throws IOException {
        client.close();
    }
}

六缘眶、DSL查詢語句

查詢所有:查詢出所有數(shù)據(jù)嘱根,一般測(cè)試用
match_all
全文檢索:利用分詞器對(duì)用戶輸入內(nèi)容分詞,然后去倒排索引庫中匹配
match_query巷懈、multi_match_query
精準(zhǔn)查詢:根據(jù)精確詞條值查詢數(shù)據(jù)该抒,一般查詢keyword、數(shù)值顶燕、日期凑保、boolean等
ids、range涌攻、term
地理查詢:根據(jù)經(jīng)緯度查詢
geo_distance欧引、geo_bounding_box
復(fù)合查詢:復(fù)合查詢可以將上述各種查詢條件組合起來,合并查詢條件
bool恳谎、function_score

1维咸、查詢所有
GET /hotel/_search
{
  "query": {
    "match_all": {
      
    }
  }
}

#全文查詢
GET /hotel/_search
{
  "query": {
    "match": {
      "name": "地區(qū)"
    }
  }
}

GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "外灘如家",
      "fields": ["brand","name","business"]
    }
  }
}
2、精確查詢
#根據(jù)詞條精確查詢
GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "北京"
      }
    }
  }
}
3惠爽、根據(jù)值的范圍查詢
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 300
      }
    }
  }
}
4癌蓖、地理查詢
GET /hotel/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 40.73,
          "lon": -74.1
        },
        "bottom_right": {
          "lat": 40.717,
          "lon": -73.99
        }
      }
    }
  }
}

GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance": "3km",
      "location": {
        "lat": 31.21,
        "lon": 121.5
      }
    }
  }
}
5、復(fù)合查詢
GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "上海外灘"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "如家"
            }
          },
          "weight": 10
        }
      ],
      "boost_mode": "multiply"
    }
  }
}
6婚肆、組合查詢
#must:必須匹配每個(gè)子查詢租副,類似“與”
#should:選擇性匹配子查詢,類似“或”
#must_not:必須不匹配较性,不參與算分用僧,類似“非”
#filter:必須匹配结胀,不參與算分
GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "city": {
            "value": "上海"
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "brand": {
            "value": "皇冠假日"
            }
          }
        },
        {
          "term": {
            "brand": {
              "value": "華美達(dá)"
            }
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "lte": 500
            }
          }
        }
      ],
      "filter": [
        {
          "range": {
            "score": {
              "gte": 45
            }
          }
        }
      ]
    }
  }
}
7、排序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": {
        "order": "desc"
      }
    },
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.034661,
          "lon": 121.612282
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

八责循、代碼實(shí)現(xiàn)查詢語句

public class HotelSearchTest {

    private RestHighLevelClient client;

    //查詢所有
    @Test
    void searchMatchAll() throws IOException {
        MatchAllQueryBuilder query = QueryBuilders.matchAllQuery();
        search(query);
    }

    //全文查詢
    @Test
    void searchMatch() throws IOException {
        MatchQueryBuilder query = QueryBuilders.matchQuery("name", "上海外灘");
        search(query);
    }

    @Test
    void searchMultiMatch() throws IOException {
        MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery("北京", "name", "brand");
        search(query);
    }

    //精準(zhǔn)查詢
    @Test
    void searchTerm() throws IOException {
        TermQueryBuilder query = QueryBuilders.termQuery("city", "深圳");
        search(query);
    }

    @Test
    void searchRange() throws IOException {
        RangeQueryBuilder query = QueryBuilders.rangeQuery("price").gte(100).lte(500);
        search(query);
    }

    /**
     * must:必須匹配每個(gè)子查詢糟港,類似“與”
     * should:選擇性匹配子查詢,類似“或”
     * must_not:必須不匹配院仿,不參與算分秸抚,類似“非”
     * filter:必須匹配,不參與算分
     */
    //組合查詢
    @Test
    void searchBool() throws IOException {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.termQuery("city", "上海"));
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(500));
        search(boolQuery);
    }

    //查詢語句抽取
    public void search(QueryBuilder queryBuilder) throws IOException {
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //準(zhǔn)備DSL
        request.source().query(queryBuilder);
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析響應(yīng)
        handleResponse(response);
    }

    //分頁查詢
    @Test
    void searchPageAndSort() throws IOException {
        int page = 1;
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //準(zhǔn)備DSL
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().sort("price", SortOrder.ASC);
        request.source().from((page - 1) * 20).size(20);
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析響應(yīng)
        handleResponse(response);
    }

    //高亮查詢
    @Test
    void searchHighlight() throws IOException {
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //準(zhǔn)備DSL
        request.source().query(QueryBuilders.matchQuery("name", "如家"));
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析響應(yīng)
        handleResponse(response);
    }

    //聚合查詢
    @Test
    void searchAggregation() throws IOException {
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //準(zhǔn)備DSL
        request.source().size(0);
        request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(20));
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析響應(yīng)
        System.out.println(response);
        //解析聚合結(jié)果
        Aggregations aggregations = response.getAggregations();
        //根據(jù)名稱獲取聚合結(jié)果
        Terms brandAgg = aggregations.get("brandAgg");
        //獲取桶
        List<? extends Terms.Bucket> buckets = brandAgg.getBuckets();
        //遍歷
        for (Terms.Bucket bucket :buckets){
            String brandName = bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            System.out.println(brandName + docCount);
        }
    }

    //解析json抽取
    public void handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "條");
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //獲取高亮結(jié)果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)) {
                HighlightField highlightField = highlightFields.get("name");
                if (highlightField != null) {
                    String name = highlightField.getFragments()[0].string();
                    hotelDoc.setName(name);
                }
            }
            System.out.println(hotelDoc);
        }
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://localhost:9200")));
    }

    @AfterEach
    void tearDown() throws IOException {
        client.close();
    }
}

九歹垫、實(shí)例練習(xí)

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public PageResult search(RequestParams params) throws IOException {
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //Query查詢
        buildBasicQuery(request, params);
        //分頁
        if (params.getPage() != null && params.getSize() != null)
            request.source().from(0).size(5);
        else
            request.source().from((params.getPage() - 1) * params.getSize()).size(params.getSize());
        //距離排序
        if (params.getLocation() != null && !params.getLocation().equals(""))
            request.source().sort(SortBuilders.
                    geoDistanceSort("location", new GeoPoint(params.getLocation())).
                    order(SortOrder.ASC).
                    unit(DistanceUnit.KILOMETERS));
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return handleResponse(response);
    }

    private void buildBasicQuery(SearchRequest request, RequestParams params) {
        //1剥汤、組合查詢
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        //輸入框內(nèi)容
        if (params.getKey() == null || params.getKey().equals(""))
            queryBuilder.must(QueryBuilders.matchAllQuery());
        else
            queryBuilder.must(QueryBuilders.matchQuery("name", params.getKey()));
        //地區(qū)
        if (params.getCity() != null && !params.getCity().equals(""))
            queryBuilder.filter(QueryBuilders.termQuery("city", params.getCity()));
        //品牌
        if (params.getBrand() != null && !params.getBrand().equals(""))
            queryBuilder.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        //星級(jí)
        if (params.getStarName() != null && !params.getStarName().equals(""))
            queryBuilder.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        //價(jià)格查詢
        if (params.getMinPrice() != null && params.getMaxPrice() != null)
            queryBuilder.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));

        //2、算分控制
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                //原始查詢
                queryBuilder,
                //function數(shù)組
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                        //其中一個(gè)function元素
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                //過濾條件
                                QueryBuilders.termQuery("isAD", true),
                                //算分函數(shù)
                                ScoreFunctionBuilders.weightFactorFunction(10)
                        )
                });
        //將條件查詢封裝
        request.source().query(functionScoreQuery);
    }

    //解析json抽取
    public PageResult handleResponse(SearchResponse response) {
        PageResult pageResult = new PageResult();
        //解析響應(yīng)
        SearchHits searchHits = response.getHits();
        //獲取總條數(shù)
        long total = searchHits.getTotalHits().value;
        pageResult.setTotal(total);
        //獲取數(shù)據(jù)集合
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> list = new ArrayList<>();
        for (SearchHit hit : hits) {
            //獲取單個(gè)數(shù)據(jù)
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //獲取排序值,距離
            Object[] sortValues = hit.getSortValues();
            if (sortValues != null && sortValues.length > 0) {
                Object value = sortValues[0];
                hotelDoc.setDistance(value);
            }
            //獲取高亮結(jié)果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)) {
                HighlightField highlightField = highlightFields.get("name");
                if (highlightField != null) {
                    String name = highlightField.getFragments()[0].string();
                    hotelDoc.setName(name);
                }
            }
            list.add(hotelDoc);
        }
        pageResult.setHotels(list);
        return pageResult;
    }

    /**
     * 聚合結(jié)果
     */
    @Override
    public Map<String, List<String>> filters(RequestParams params) throws IOException {
        Map<String, List<String>> map = new HashMap<>();
        //準(zhǔn)備Request
        SearchRequest request = new SearchRequest("hotel");
        //準(zhǔn)備DSL
        //Query查詢
        buildBasicQuery(request, params);
        //聚合查詢
        buildAggregation(request);
        //發(fā)送請(qǐng)求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析響應(yīng)
        System.out.println(response);
        //解析聚合結(jié)果
        Aggregations aggregations = response.getAggregations();
        //根據(jù)名稱獲取聚合結(jié)果
        List<String> cityList = getAggByName(aggregations, "cityAgg");
        List<String> brandList = getAggByName(aggregations, "brandAgg");
        List<String> starList = getAggByName(aggregations, "starAgg");
        map.put("城市", cityList);
        map.put("品牌", brandList);
        map.put("星級(jí)", starList);
        return map;
    }

    private void buildAggregation(SearchRequest request) {
        request.source().size(0);
        request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));
        request.source().aggregation(AggregationBuilders.terms("cityAgg").field("city").size(100));
        request.source().aggregation(AggregationBuilders.terms("starAgg").field("starName").size(100));
    }

    public List<String> getAggByName(Aggregations aggregations, String agg) {
        //聚合集合
        List<String> list = new ArrayList<>();
        //根據(jù)聚合名稱獲取聚合數(shù)據(jù) m
        Terms terms = aggregations.get(agg);
        //獲取聚合數(shù)據(jù)結(jié)果集
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        //遍歷
        for (Terms.Bucket bucket : buckets) {
            String brandName = bucket.getKeyAsString();
            list.add(brandName);
        }
        return list;
    }
} 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末排惨,一起剝皮案震驚了整個(gè)濱河市吭敢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌暮芭,老刑警劉巖鹿驼,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異辕宏,居然都是意外死亡畜晰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門匾效,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恤磷,你說我怎么就攤上這事面哼。” “怎么了扫步?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵魔策,是天一觀的道長。 經(jīng)常有香客問我河胎,道長闯袒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任游岳,我火速辦了婚禮政敢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胚迫。我一直安慰自己喷户,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布访锻。 她就那樣靜靜地躺著褪尝,像睡著了一般闹获。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上河哑,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天避诽,我揣著相機(jī)與錄音,去河邊找鬼璃谨。 笑死沙庐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的睬罗。 我是一名探鬼主播轨功,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼容达!你這毒婦竟也來了古涧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤花盐,失蹤者是張志新(化名)和其女友劉穎羡滑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算芯,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柒昏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熙揍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片职祷。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖届囚,靈堂內(nèi)的尸體忽然破棺而出有梆,到底是詐尸還是另有隱情,我是刑警寧澤意系,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布泥耀,位于F島的核電站,受9級(jí)特大地震影響蛔添,放射性物質(zhì)發(fā)生泄漏痰催。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一迎瞧、第九天 我趴在偏房一處隱蔽的房頂上張望夸溶。 院中可真熱鬧,春花似錦凶硅、人聲如沸蜘醋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽压语。三九已至啸罢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胎食,已是汗流浹背扰才。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厕怜,地道東北人衩匣。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像粥航,于是被迫代替她去往敵國和親琅捏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容