【问题标题】:Elasticsearch match all query using Java APIElasticsearch 使用 Java API 匹配所有查询
【发布时间】:2020-04-28 03:40:06
【问题描述】:

我们使用的是 Elasticsearch 7.3.1 版和 Java API。

我们正在实施“免费搜索”,这意味着在 Elasticsearch 中每个段的 ALL 字段中搜索一个值。如果该值至少出现在段的一个字段中,则应返回。

到目前为止,我们已经使用了以下代码:QueryBuilders.multiMatchQuery(value),并且效果很好。

至于今天,我们在映射文件中添加了一些嵌套(Elasticsearch数据类型)类型的字段。

更改后,上面的代码不再返回预期的结果。

如何在不指定要搜索的每个字段的情况下在段中的ALL字段中实现搜索?

【问题讨论】:

    标签: java elasticsearch kibana


    【解决方案1】:

    您可以实现_all 以前的elasticsearch 版本的逻辑(我相信这是在版本6 之后删除的)。

    PUT stackoverflow
    {
      "mappings": {
        "properties": {
          "all": {
            "type": "text"
          },
          "group": {
            "type": "text",
            "copy_to": "all"
          },
          "user": {
            "type": "nested",
            "properties": {
              "email": {
                "type": "keyword",
                "copy_to": "all"
              },
              "info": {
                "type": "text",
                "copy_to": "all"
              }
            }
          }
        }
      }
    }
    

    基本上你添加copy_to 参数。

    PUT stackoverflow/_doc/1
    {
      "group" : "programmers",
      "user" : [
        {
          "email" : "test@gmail.com",
          "info" :  "java developer"
        },
        {
          "email" : "demo@wikipedia.org",
          "info" :  "css guru"
        }
      ]
    }
    

    然后您可以搜索 all 字段

    GET stackoverflow/_search
    {
      "query": {
        "match": {
          "all": "guru"
        }
      }
    }
    

    更新

    这是一个示例,说明如何修改您的查询以使其在没有copy_to 的情况下工作

    GET stackoverflow/_search
    {
      "query": {
        "bool": {
          "minimum_should_match": 1,
          "should": [
            {
              "multi_match": {
                "query": "SEARCH_INPUT_HERE",
                "fields": [
                  "group"
                ]
              }
            },
            {
              "nested": {
                "path": "user",
                "query": {
                  "multi_match": {
                    "query": "SEARCH_INPUT_HERE",
                    "fields": [
                      "user.email", "user.info"
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    }
    

    更新 2

    public static void main(String[] args) {
        String queryInput = "QUERY_INPUT_HERE";
        String[] nested = {"user", "product"};
    
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(queryInput, "*");
    
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> shouldQueryBuilders = boolQueryBuilder.should();
    
        shouldQueryBuilders.add(multiMatchQueryBuilder);
        for(String path : nested) {
            NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(path, multiMatchQueryBuilder, ScoreMode.Avg);
            shouldQueryBuilders.add(nestedQueryBuilder);
        }
    
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);
    
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.source(searchSourceBuilder);
        searchRequest.indices("MY_INDEX");
    
        System.out.println(searchRequest.toString());
    }
    

    输出

    {
      "query": {
        "bool": {
          "should": [
            {
              "multi_match": {
                "query": "QUERY_INPUT_HERE",
                "fields": [
                  "*^1.0"
                ],
                "type": "best_fields",
                "operator": "OR",
                "slop": 0,
                "prefix_length": 0,
                "max_expansions": 50,
                "zero_terms_query": "NONE",
                "auto_generate_synonyms_phrase_query": true,
                "fuzzy_transpositions": true,
                "boost": 1.0
              }
            },
            {
              "nested": {
                "query": {
                  "multi_match": {
                    "query": "QUERY_INPUT_HERE",
                    "fields": [
                      "*^1.0"
                    ],
                    "type": "best_fields",
                    "operator": "OR",
                    "slop": 0,
                    "prefix_length": 0,
                    "max_expansions": 50,
                    "zero_terms_query": "NONE",
                    "auto_generate_synonyms_phrase_query": true,
                    "fuzzy_transpositions": true,
                    "boost": 1.0
                  }
                },
                "path": "user",
                "ignore_unmapped": false,
                "score_mode": "avg",
                "boost": 1.0
              }
            },
            {
              "nested": {
                "query": {
                  "multi_match": {
                    "query": "QUERY_INPUT_HERE",
                    "fields": [
                      "*^1.0"
                    ],
                    "type": "best_fields",
                    "operator": "OR",
                    "slop": 0,
                    "prefix_length": 0,
                    "max_expansions": 50,
                    "zero_terms_query": "NONE",
                    "auto_generate_synonyms_phrase_query": true,
                    "fuzzy_transpositions": true,
                    "boost": 1.0
                  }
                },
                "path": "product",
                "ignore_unmapped": false,
                "score_mode": "avg",
                "boost": 1.0
              }
            }
          ],
          "adjust_pure_negative": true,
          "boost": 1.0
        }
      }
    }
    

    【讨论】:

    • 这个“copy_to”也将字段复制到全部?它不会使用2倍的空间吗?没有其他办法吗?
    • 这是最简单的方法,无需在每次添加字段时更改搜索。它不会增加一倍的大小,但会增加它。我将在没有 copy_to 的答案中添加一个示例。
    • 我添加了一个查询示例,以便它可以处理嵌套和简单字段。
    • 对嵌套字段的查询以及另一个查询是 multi_match 查询。字段部分可以是通配符*,表示所有字段。如果您想要更多控制权,您可以这样做 "fields": ["*"]"fields": ["user.*"]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2016-02-25
    • 2013-11-10
    相关资源
    最近更新 更多