elasticsearch bool查询必须与OR结合使用


181

我目前正在尝试将基于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)或(信息中包含foo AND bar)的所有文档。在此之后,按条件state = 1过滤结果,并增强具有图像的文档。”

我一直在尝试将布尔查询与MUST一起使用,但是我无法将布尔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
            }
          }
        }
      ]
    }
  }
}

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

有没有人有办法解决吗?

非常感谢。

**更新**

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


1
有上结合ElasticSearch有一个好的文档查询的位置:elastic.co/guide/en/elasticsearch/guide/current/...
Mr.Coffee

Answers:


423
  • 拼写
  • AND 必须拼写
  • NOR拼写为should_not

例:

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

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

您还可以执行更复杂的OR版本,例如,如果要匹配5个中的至少3个,则可以在“应该”下指定5个选项,并将“最小数量”设置为3。

感谢Glen Thompson和Sebastialonso找到我以前不太合适的嵌套位置。

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


2
是否会将其拉到should上层bool,并包括minimum_should_match: 1工作?
Sid

18
当我尝试这个例子时,我会回来的[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]。这是否取决于版本?
DanneJ '17

25
他们为什么不在文档中添加如此简单的示例和说明!文档中的示例非常令人困惑。
Nikhil Owalekar,

20
6个月后,阅读所有Elastic文档,这是我第一次完全了解如何实现布尔逻辑。我认为官方文档不够清晰。
Sebastialonso

3
@Amir我可以为您清理哪些错误信息?在上面显示的上下文中,默认minimum_should值为1,bool如果至少一项匹配,则包装该结果将导致该组为true,如果不匹配则为false。创建此答案的动机是,我正在解决此类问题,而在此类站点上可以找到的可用文档甚至答案充其量也无济于事,因此我一直在进行研究,直到我感到自己扎实的基础发生了什么。我很高兴欢迎任何关于如何进一步改善答案的建议。
丹尼尔·法克雷尔

68

我终于设法创建了一个查询,该查询完全可以实现我想要的功能:

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

这是查询:

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
      }
    }
   }
 ]

玩得开心:)


28
哇靠。有谁有更好的解决方案?感谢您发布此信息,但这绝对太复杂了,无法在查询中实现逻辑或。
nackjicholson

thnx,您拯救了我的一天)
cubbiu

3
此查询不仅使用不必要的语法,而且使用了已弃用的语法。@ daniel-fackrell答案应该被接受。
埃里克·艾尔福德

4
@EricAlford 2015年的答案基于早期版本的ES。随时提供更好的解决方案。
杰西

想法:接管/派生ElasticSearch,以一种用户友好的方式对其进行重写,向其中添加简单的查询语言,WIN!我们只需要资金。算我一个!还有谁 ?
Sliq

16

这样,您可以使用Kibana在一个外部布尔查询中嵌套多个布尔查询,

布尔值表示我们正在使用布尔值

必须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中嵌套查询的方式

“布尔”中有更多类型,例如-

  1. 过滤

  2. 一定不


您的答案是完全正确的,但是有点笨拙,如果您愿意,这对您来说是个小建议-您必须对其进行适当的编辑。可能它会给您更多有关此答案的信息:)祝您有美好的一天。
Dhwanil Patel

6

我最近也不得不解决这个问题,经过大量的试验和错误,我想到了这一点(在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

希望这对某人有帮助!


0
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

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

您可以检查以下内容:https : //github.com/Smile-SA/elasticsuite/issues/972


0

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

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)"
    }
  }
}

也就是说,您可能想要使用布尔查询,例如您已经发布的查询,或者甚至是两者的组合。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.