【问题标题】:Elasticsearch must_not not working with filter clauseElasticsearch must_not 不能使用过滤器子句
【发布时间】:2023-03-05 20:57:01
【问题描述】:

我正在从事医疗项目,我有多个问题以及附加的主题。问题是以下代码可以正常工作,但它没有考虑“must_not”过滤器,而与“must”子句一起工作正常。帮我解决这个问题。

GET stopdata/_search
{
  "query": {
    "function_score": {
      "query": {
        "filtered": {
          "query": {
            "match": {
              "question": "Hello Dr. Iam suffering from fever with cough nd cold since 3 days"
            }
          }
        }
      },
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "topics": [
                  "fever",
                  "cough"
                ]
              }
            }
          ],
          "must_not": [
            {
              "terms": {
                "topics": [
                  "children",
                  "child",
                  "childrens health"
                ]
              }
            }
          ]
        }
      },
      "random_score": {}
    }
  },
  "highlight": {
    "fields": {
      "keyword": {}
    }
  }
}

另外,我需要将代码转换为 Java,我正在尝试但坚持使用以下代码。

Set<String> mustNot = new HashSet<String>();
mustNot.add("child");
mustNot.add("children");
mustNot.add("childrens health");

Set<String> must = new HashSet<String>();
must.add("fever");
must.add("cough");

FunctionScoreQueryBuilder fsqb = new FunctionScoreQueryBuilder(QueryBuilders.matchQuery("question", "Hello Dr. Iam suffering from fever with cough nd cold since 3 days"));
fsqb.add(ScoreFunctionBuilders.randomFunction((new Date()).getTime()));

BoolQueryBuilder bqb = boolQuery()
        .mustNot(termsQuery("topics", mustNot));

SearchResponse response1 = client.prepareSearch("stopdata")
        .setQuery(fsqb)
        .execute()
        .actionGet();

System.out.println(response1.getHits().getTotalHits());

'stopdata'索引的映射如下

{
   "stopdata": {
      "mappings": {
         "questions": {
            "properties": {
               "answers": {
                  "type": "string"
               },
               "id": {
                  "type": "long"
               },
               "question": {
                  "type": "string",
                  "analyzer": "my_english"
               },
               "relevantQuestions": {
                  "type": "long"
               },
               "topics": {
                  "type": "string"
               }
            }
         }
      }
   }
}

为上述索引添加样本数据

"question": "My son of age 8 months is suffering from cough and cold and fever. What treatment I have to follow?"
"topics": [
  "Cough",
  "Fever",
  "Hydration",
  "Nutrition",
  "Tens",
  "Childrens health"
]

"question": "Hi.My daughter, 4 years old , has on and of fever  with severe coughing and colds for 3 days now.She vomited as well last night.Do you think it's viral?"
"topics": [
  "Vomiting",
  "Flu",
  "Cough",
  "Fever",
  "Pneumonia",
  "Meningitis",
  "Tamiflu",
  "Incision",
  "Childrens health",
  "Oseltamivir"
]

"question": "If you have a fever of 101 with chills and sweats for 2 day with a slight cough, should you go to the drs or let is wear off?"
"topics": [
  "Cough",
  "Fever"
]

【问题讨论】:

    标签: java elasticsearch elasticsearch-java-api


    【解决方案1】:

    我看到的是整个filter 部分放错了位置,它应该进入filtered 查询中,因为function_score 元素的根部没有filter 元素(请参阅official docs )。因此,您的查询首先应该如下所示 + 您应该使用 POST 而不是 GET,因为您正在发送有效负载:

    POST stopdata/_search
    {
      "query": {
        "function_score": {
          "query": {
            "filtered": {
              "query": {
                "match": {
                  "question": "Hello Dr. Iam suffering from fever with cough nd cold since 3 days"
                }
              },
              "filter": {
                "bool": {
                  "must": [
                    {
                      "terms": {
                        "topics": [
                          "fever",
                          "cough"
                        ]
                      }
                    }
                  ],
                  "must_not": [
                    {
                      "terms": {
                        "topics": [
                          "children",
                          "child",
                          "childrens health"
                        ]
                      }
                    }
                  ]
                }
              }
            }
          },
          "random_score": {}
        }
      },
      "highlight": {
        "fields": {
          "keyword": {}
        }
      }
    }
    

    现在用Java编写所有这些,它是这样的:

    Set<String> mustNot = new HashSet<String>();
    mustNot.add("child");
    mustNot.add("children");
    mustNot.add("childrens health");
    
    Set<String> must = new HashSet<String>();
    must.add("fever");
    must.add("cough");
    
    MatchQueryBuilder query = QueryBuilders.matchQuery("question", "Hello Dr. Iam suffering from fever with cough nd cold since 3 days");
    
    BoolFilterBuilder filter = FilterBuilders.boolFilter()
        .must(FilterBuilders.termsFilter("topics", must))
        .mustNot(FilterBuilders.termsFilter("topics", mustNot));
    
    FilteredQueryBuilder fqb = QueryBuilders.filteredQuery(query, filter);
    
    FunctionScoreQueryBuilder fsqb = QueryBuilders.functionScoreQuery(fqb);
    fsqb.add(ScoreFunctionBuilders.randomFunction((new Date()).getTime()));
    
    SearchResponse response1 = client.prepareSearch("stopdata")
            .setQuery(fsqb)
            .execute()
            .actionGet();
    
    System.out.println(response1.getHits().getTotalHits());
    

    更新

    must_notchildrens health 不匹配的原因是因为 topics 字段被分析,因此 Childrens health 被标记化并被分析为两个标记 childrenshealth,从而尝试terms 匹配 childrens health 不会产生任何结果。也许,分成两个术语会有所帮助:

                  "must_not": [
                    {
                      "terms": {
                        "topics": [
                          "children",
                          "child",
                          "childrens", 
                          "health"
                        ]
                      }
                    }
                  ]
    

    【讨论】:

    • 我仍然得到主题“儿童健康”的结果,结果没有你建议的变化。
    • 我只是在修复 1) 查询中的语义问题和 2) 帮助您构建 Java 等价物。最后,匹配的内容取决于您的数据以及 topics 字段的映射方式,请随时分享更多信息。
    • 感谢您的帮助 Val。我已经添加了映射和示例数据。另外,我在FilteredQueryBuilder fqb = QueryBuilders.filteredQuery(query, filter);'The method filteredQuery(QueryBuilder, FilterBuilder) in the type QueryBuilders is not applicable for the arguments (MatchQueryBuilder, BoolQueryBuilder)'中收到错误
    • 顺便问一下你运行的是什么版本的ES?
    • 您需要编辑您的问题,而不是我的答案 :) 我拒绝了这两个编辑并改为编辑您的问题。随意总结一下。
    猜你喜欢
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多