Elasticsearch: Terms lookup查询方案

场景:商品池索引 sku_data,需要过滤编码字段skuCode

Terms

使用terms查询商品编码

{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "skuCode": [
              "7700220626",
              "7700159221"
            ]
          }
        }
      ]
    }
  }
}

terms查询字词限制为65535,上面的查询参数skuCode是静态参数,如果要从其他索引动态传入,可以使用 Terms lookup

Terms lookup

参数:

index
(必需,字符串)从中获取字段值的索引的名称。

id
(必需,字符串)要从中获取字段值的文档的ID。

path
(必需,字符串)要从中获取字段值的字段名称。 Elasticsearch 使用这些值作为查询的搜索词。 如果字段值包含嵌套的内部对象的数组,则可以使用点表示法语法访问这些对象。

routing
(可选,字符串)从中获取术语值的文档的自定义路由值。 如果在为文档建立索引时提供了自定义路由值,则此参数是必需的。

例子

用户拥有的商品索引user_skus

用户id=10000的文档

{
        "_index" : "user_skus",
        "_type" : "_doc",
        "_id" : "10000",
        "_score" : 1.0,
        "_source" : {
          "skus" : [
            "1401027979",
            "1401027980",
            "1401027978",
            "1401027981"
          ]
        }
      }
}

使用Terms lookup筛选skuCode字段,此查询将中user_skus索引,文档id10000,skus字段的商品作为参数传入terms的数组

GET sku_data/_search
{
"query": { "bool": { "filter": [ { "terms": { "skuCode": { "index": "user_skus", "id": "10000", "path": "skus" } } } ] } } }

Terms lookup也有查询字词限制,限制65535。可以修改动态参数index.max_terms_count来提高限制,但会影响查询效率。(公司项目中30万字词查询了3秒)

修改terms参数语句

PUT sku_data/_settings
{
  "index.max_terms_count": 500000
}

同步数据时一个请求无法添加几十万条商品数据,需要拆分商品,发送多次请求追加商品

添加商品

POST user_skus/_doc/10000
{
  "skus": [
    "1401027979",
    "1401027980"
  ]
}

但再次请求会覆盖掉skus字段,不会追加。想要给skus数组增加元素需要使用script脚本

Script

文档id=10000,字段skus数组添加元素

POST user_skus/_doc/10000/_update
{
  "script":{
    "inline": "ctx._source.skus.addAll(params.new_tag)",
    "params" : {
          "new_tag" : ["110022","55280"]
     }
  }
}

添加后的元素为

"_source" : {
    "skus" : [
      "1401027979",
      "1401027980",
      "110022",
      "55280" 
] }

Java实现

Terms lookup查询

 1 public SearchResponse termsLookUpSearch() throws IOException {
 2     SearchRequest searchRequest = new SearchRequest("sku_data");
 3     BoolQueryBuilder boolQuery = new BoolQueryBuilder();
 4     String index = "user_skus";
 5     String id = "100000";
 6     String path = "skus";
 7     boolQuery.filter(QueryBuilders.termsLookupQuery("skuCode", new TermsLookup(index, id, path)));
 8     SearchSourceBuilder source = SearchSourceBuilder.searchSource();
 9     source.query(boolQuery);
10     searchRequest.source(source);
11     return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
12 }

Script脚本更新文档

    /**
     * 多个文档增加skus字段
     * @param dataMap
     * {
     *     "10000": ["1102552","11023658","112562"],
     *     "10002": ["7745211","7742562"]
     * }
     */
    public void addUserSkus(Map<String, List<String>> dataMap) {
        String userSkusIndex = "user_skus";
        BulkRequest bulkRequest = new BulkRequest();

        for (Map.Entry<String, List<String>> entry : dataMap.entrySet()) {
            //没有文档则新增
            IndexRequest index = new IndexRequest(userSkusIndex);
            index.id(entry.getKey());
            Map<String, Object> map = new HashedMap<>();
            map.put("skus", entry.getValue());
            index.source(map);
            //修改使用script脚本
            UpdateRequest update = new UpdateRequest(userSkusIndex, entry.getKey());
            Map<String, Object> params = new HashedMap<>();
            params.put("new_tag", entry.getValue());
            Script script = new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG,
                    "ctx._source.skus.addAll(params.new_tag)", params);
            update.script(script);
            //新增或修改
            update.upsert(index);
            bulkRequest.add(update);
        }
        try {
            BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

*为保护使用者隐私,以上引用索引均采用化名

 

参考文档:

https://elasticstack.blog.csdn.net/article/details/112857984

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html#query-dsl-terms-lookup官方文档

posted @ 2022-09-29 16:54  吾乃闪耀的知识灯塔  阅读(1159)  评论(0编辑  收藏  举报