elasticsearch bool 查询必须与 OR 结合

Posted

技术标签:

【中文标题】elasticsearch bool 查询必须与 OR 结合【英文标题】:elasticsearch bool query combine must with OR 【发布时间】:2015-04-16 19:21:24 【问题描述】:

我目前正在尝试将基于 solr 的应用程序迁移到 elasticsearch。

我有这个 lucene 查询

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)

据我了解,这是 MUST 子句与布尔 OR 的组合:

“获取所有包含 (foo AND bar in name) OR (foo AND bar in info) 的文档。然后按条件 state=1 过滤结果并提升具有图像的文档。”

我一直在尝试对 MUST 使用 bool 查询,但我未能将 boolean OR 放入 must 子句。这是我所拥有的:

GET /test/object/_search

  "from": 0,
  "size": 20,
  "sort": 
    "_score": "desc"
  ,
  "query": 
    "bool": 
      "must": [
        
          "match": 
            "name": "foo"
          
        ,
        
          "match": 
            "name": "bar"
          
        
      ],
      "must_not": [],
      "should": [
        
          "match": 
            "has_image": 
              "query": 1,
              "boost": 100
            
          
        
      ]
    
  

如您所见,“信息”的 MUST 条件缺失。

有人有解决办法吗?

非常感谢。

** 更新 **

我已经更新了我的 elasticsearch 查询并摆脱了该功能得分。我的基本问题仍然存在。

【问题讨论】:

这里有一个很好的关于结合 ElasticSearch 查询的文档:elastic.co/guide/en/elasticsearch/guide/current/… 从 v7.10 开始,这是关于布尔查询的新文档:elastic.co/guide/en/elasticsearch/reference/current/… 我确实相信可以通过示例改进文档,以便更清楚地了解像这个 OR 问题这样的简单案例。 . 【参考方案1】: OR 拼写为 should AND 拼写为 must NOR 拼写为 should_not

例子:

您想查看所有项目(圆形 AND(红色或蓝色)):


    "query": 
        "bool": 
            "must": [
                
                    "term": "shape": "round"
                ,
                
                    "bool": 
                        "should": [
                            "term": "color": "red",
                            "term": "color": "blue"
                        ]
                    
                
            ]
        
    

您还可以做更复杂的 OR 版本,例如,如果您想匹配至少 5 个中的 3 个,您可以在“should”下指定 5 个选项并将“minimum_should”设置为 3。

感谢 Glen Thompson 和 Sebastialonso 发现我之前的嵌套不太正确。

也感谢 Fatmajk 指出“术语”在 ElasticSearch 6 中变为“匹配”。

【讨论】:

会将should 拉入上层bool,并包括minimum_should_match: 1 工作吗? 当我尝试这个例子时,我得到了[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]。这是否取决于版本? 他们为什么不在文档中添加这样一个简单的示例和解释!文档中的示例非常令人困惑。 6个月后,阅读所有Elastic文档,这是我第一次完全理解如何实现布尔逻辑。在我看来,官方文档不够清晰。 @Amir 我可以为您清理哪些不准确之处?在上面显示的上下文中,默认的 minimum_should 是 1,如果将其包装在 bool 中,则如果至少有一项匹配,则该组为 true,如果不匹配则为 false。我创建这个答案的动机是我正在解决这类问题,可用的文档,甚至我可以在这样的网站上找到的答案充其量是没有帮助的,所以我一直在研究,直到我觉得自己掌握得很好发生了什么。我很高兴欢迎任何关于如何进一步改进答案的建设性指示。【参考方案2】:

我终于设法创建了一个完全符合我要求的查询:

过滤的嵌套布尔查询。 我不确定为什么没有记录。也许这里有人可以告诉我?

这里是查询:

GET /test/object/_search

  "from": 0,
  "size": 20,
  "sort": 
    "_score": "desc"
  ,
  "query": 
    "filtered": 
      "filter": 
        "bool": 
          "must": [
            
              "term": 
                "state": 1
              
            
          ]
        
      ,
      "query": 
        "bool": 
          "should": [
            
              "bool": 
                "must": [
                  
                    "match": 
                      "name": "foo"
                    
                  ,
                  
                    "match": 
                      "name": "bar"
                    
                  
                ],
                "should": [
                  
                    "match": 
                      "has_image": 
                        "query": 1,
                        "boost": 100
                      
                    
                  
                ]
              
            ,
            
              "bool": 
                "must": [
                  
                    "match": 
                      "info": "foo"
                    
                  ,
                  
                    "match": 
                      "info": "bar"
                    
                  
                ],
                "should": [
                  
                    "match": 
                      "has_image": 
                        "query": 1,
                        "boost": 100
                      
                    
                  
                ]
              
            
          ],
          "minimum_should_match": 1
        
          
    
  

在伪 SQL 中:

SELECT * FROM /test/object
WHERE 
    ((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1

请记住,这取决于您的文档字段分析和映射如何在内部处理 name=foo。这可以从模糊到严格的行为变化。

"minimum_should_match": 1 表示,至少有一个 should 语句必须为真。

此语句意味着,只要结果集中有一个包含 has_image:1 的文档,它就会被提升 100 倍。这会改变结果排序。

"should": [
  
    "match": 
      "has_image": 
        "query": 1,
        "boost": 100
      
    
   
 ]

祝大家玩得开心:)

【讨论】:

天哪。有没有人有更好的解决方案?感谢您发布此内容,但这对于在查询中实现逻辑 OR 来说绝对是太复杂了。 谢谢,你拯救了我的一天) 这个查询不仅不必要地长,而且它使用了不推荐使用的语法。 @daniel-fackrell 答案应该是被接受的。 @EricAlford 这个 2015 年的答案基于早期版本的 ES。随时提供更好的解决方案。 想法:接管/fork ElasticSearch,以用户友好的方式重写它,添加简单的查询语言,赢了!我们只需要资金。算我一个!还有谁?【参考方案3】:

这是您可以在一个外部 bool 查询中嵌套多个 bool 查询的方法 这个使用 Kibana,

bool 表示我们使用的是布尔值 必须用于AND 应该代表
GET my_inedx/my_type/_search

  "query" : 
     "bool":              //bool indicates we are using boolean operator
          "must" : [       //must is for **AND**
               
                 "match" : 
                       "description" : "some text"  
                   
               ,
               
                  "match" :
                        "type" : "some Type"
                   
               ,
               
                  "bool" :           //here its a nested boolean query
                        "should" : [  //should is for **OR**
                               
                                 "match" : 
                                     //ur query
                                
                               ,
                                
                                  "match" :  
                                    
                             ]
                        
               
           ]
      
  

这是在 ES 中嵌套查询的方法


“bool”中有更多类型,如,

    过滤器 must_not

【讨论】:

您的答案完全正确,但是有点笨拙,如果您愿意,这是对您的一个小建议-您必须正确编辑它。可能它会让你更喜欢这个答案:)祝你有美好的一天。【参考方案4】:

我最近也不得不解决这个问题,经过大量试验和错误后,我想出了这个(在 php 中,但直接映射到 DSL):

'query' => [
    'bool' => [
        'should' => [
            ['prefix' => ['name_first' => $query]],
            ['prefix' => ['name_last' => $query]],
            ['prefix' => ['phone' => $query]],
            ['prefix' => ['email' => $query]],
            [
                'multi_match' => [
                    'query' => $query,
                    'type' => 'cross_fields',
                    'operator' => 'and',
                    'fields' => ['name_first', 'name_last']
                ]
            ]
        ],
        'minimum_should_match' => 1,
        'filter' => [
            ['term' => ['state' => 'active']],
            ['term' => ['company_id' => $companyId]]
        ]
    ]
]

在 SQL 中映射到这样的东西:

SELECT * from <index> 
WHERE (
    name_first LIKE '<query>%' OR
    name_last LIKE '<query>%' OR
    phone LIKE  '<query>%' OR
    email LIKE '<query>%'
)
AND state = 'active'
AND company_id = <query>

这一切的关键是minimum_should_match 设置。没有这个filter 完全覆盖should

希望这对某人有所帮助!

【讨论】:

这似乎是比当前接受的答案更好的答案【参考方案5】:

如果您使用的是 Solr 的默认或 Lucene 查询解析器,您几乎总是可以将其放入 query string 查询中:

POST test/_search

  "query": 
    "query_string": 
      "query": "(( name:(+foo +bar) OR info:(+foo +bar)  )) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)"
    
  

也就是说,您可能想要使用boolean query,就像您已经发布的那个一样,或者甚至是两者的组合。

【讨论】:

【参考方案6】:
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

must 中,您需要添加要使用AND 的查询条件数组,在should 中,您需要添加要使用OR 的查询条件。

你可以查看这个:https://github.com/Smile-SA/elasticsuite/issues/972

【讨论】:

以上是关于elasticsearch bool 查询必须与 OR 结合的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch(七)——复合查询

四十五 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的bool组合查询

如何在Elasticsearch查询中结合“必须”和“应该”?

初识ElasticSearch -文档查询之bool查询

初识ElasticSearch -文档查询之bool查询

ElasticSearch Bool Query JAVA API