Elasticsearch的一些高级用法

精确到字母的自动补全业务:
public List suggest(String key) throws Exception {
SearchRequest.Builder builder = new SearchRequest.Builder();
builder.index("items");
builder.suggest(s -> s
.suggesters("suggestion_suggest", ss -> ss
.completion(c -> c
.field("suggestion")
.size(10)
.skipDuplicates(true))
.text(key))
);
SearchRequest request = builder.build();
SearchResponse response = esClient.search(request, ItemDoc.class);
Map<String, List<Suggestion>> suggest = response.suggest();
List<Suggestion> suggestion_suggest = suggest.get("suggestion_suggest");
List list=new ArrayList<>();
suggestion_suggest.stream().forEach(suggestion -> {
suggestion.completion().options().forEach(option -> {
String text = option.text();
list.add(text);
});
});
return list;
}

数据聚合,从最外层开始进行筛选与聚合
现在需要统计同一分类下的不同品牌的商品数量
GET /items/_search
{
"aggs" : {
"category_agg" : {
"aggs" : {
"brand_agg" : {
"terms" : {
"field" : "brand",
"size" : 20
}
}
},
"terms" : {
"field" : "category",
"size" : 20
}
}
},
"size" : 0
}
结果
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4002,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"category_agg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "拉杆箱",
"doc_count" : 2088,
"brand_agg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 594,
"buckets" : [
{
"key" : "美旅箱包",
"doc_count" : 187
},
{
"key" : "PointKid",
"doc_count" : 128
},
{
"key" : "汉客",
"doc_count" : 120
},
{
"key" : "新秀丽",
"doc_count" : 104
},
{
"key" : "DELSEY",
"doc_count" : 99
},
{
"key" : "莎米特",
"doc_count" : 91
},
{
"key" : "文森保罗",
"doc_count" : 89
},
{
"key" : "旅行之家",
"doc_count" : 78
},
{
"key" : "爱华仕",
"doc_count" : 72
},
{
"key" : "梵地亚",
"doc_count" : 70
},
{
"key" : "瑞动",
"doc_count" : 66
},
{
"key" : "银座",
"doc_count" : 59
},
{
"key" : "Diplomat",
"doc_count" : 58
},
{
"key" : "博兿",
"doc_count" : 46
},
{
"key" : "宾豪",
"doc_count" : 41
},
{
"key" : "卡拉羊",
"doc_count" : 40
},
{
"key" : "瑞界",
"doc_count" : 38
},
{
"key" : "Kamiliant",
"doc_count" : 37
},
{
"key" : "ITO",
"doc_count" : 36
},
{
"key" : "EAZZ",
"doc_count" : 35
}
]
}
},

nested的使用
查询商品颜色是粉色的商品。
GET /items/_search
{
"query": {
"nested": {
"path": "attr_list",
"query": {
"bool": {
"must": [
{
"term": {
"attr_list.name": {
"value": "颜色"
}
}
},
{
"term": {
"attr_list.value": {
"value": "白色"
}
}
}
]
}
}
}
}
}

一下是数据导入
{
"_index" : "items",
"_type" : "_doc",
"_id" : "317578",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"id" : "317578",
"name" : "RIMOWA 21寸托运箱拉杆箱 SALSA AIR系列果绿色 820.70.36.4",
"price" : 28900,
"stock" : 9985,
"image" : "https://m.360buyimg.com/mobilecms/s720x720_jfs/t6934/364/1195375010/84676/e9f2c55f/597ece38N0ddcbc77.jpg!q70.jpg.webp",
"category" : "拉杆箱",
"brand" : "RIMOWA",
"sold" : 0,
"commentCount" : 0,
"isAD" : false,
"updateTime" : [
2024,
10,
25,
17,
52,
8
],
"attr_list" : [
{
"name" : "大小",
"value" : "60*40"
},
{
"name" : "颜色",
"value" : "白色"
}
]
}
}

最后将属性聚合出来
GET /items/_search
{
"size": 0,
"aggs": {
"attr_aggs": {
"nested": {
"path": "attr_list"
},
"aggs": {
"attr_name_aggs": {
"terms": {
"field": "attr_list.name",
"size": 10
},
"aggs": {
"attr_value_aggs": {
"terms": {
"field": "attr_list.value",
"size": 10
}
}
}
}
}
}
}
}

结果大致为
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 200,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"attr_aggs" : {
"doc_count" : 400,
"attr_name_aggs" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "大小",
"doc_count" : 200,
"attr_value_aggs" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "12080",
"doc_count" : 100
},
{
"key" : "60
40",
"doc_count" : 100
}
]
}
},
{
"key" : "颜色",
"doc_count" : 200,
"attr_value_aggs" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "白色",
"doc_count" : 100
},
{
"key" : "黑色",
"doc_count" : 100
}
]
}
}
]
}
}
}
}
java代码:
@Test
void testNestedAggs() throws Exception {

SearchRequest.Builder builder = new SearchRequest.Builder();
builder.index("items2");
builder.size(0);
builder.aggregations("attr_aggs", a -> a
        .nested(n -> n.path("attr_list"))
        .aggregations("attr_name_aggs", a1 -> a1
                .terms(t -> t
                        .field("attr_list.name")
                        .size(10))
                .aggregations("attr_value_aggs", a2 -> a2
                        .terms(t -> t
                                .field("attr_list.value")
                        )
                )
        )
);
SearchRequest build = builder.build();
SearchResponse<ItemDoc> response = esClient.search(build, ItemDoc.class);
Map<String, Aggregate> aggregations = response.aggregations();
Aggregate attrAggs = aggregations.get("attr_aggs");
//解析结果
NestedAggregate nested = attrAggs.nested();
Map<String, Aggregate> attrNameAggs = nested.aggregations();
Aggregate aggregate = attrNameAggs.get("attr_name_aggs");
aggregate.sterms().buckets().array().forEach(bucket -> {
    String key = bucket.key().stringValue();
    Long docCount = bucket.docCount();
    log.info("属性名:{},属性值数量:{}", key, docCount);
    Map<String, Aggregate> aggregations1 = bucket.aggregations();
    Aggregate attrValueAggs = aggregations1.get("attr_value_aggs");
    attrValueAggs.sterms().buckets().array().forEach(bucket1 -> {
        String key1 = bucket1.key().stringValue();
        Long docCount1 = bucket1.docCount();
        log.info("属性值:{},属性值数量:{}", key1, docCount1);
    });
});

}

posted @ 2025-03-24 20:57  人生何处不青山啊  阅读(30)  评论(0)    收藏  举报