elasticsearch bool query必须与OR结合使用

时间:2015-02-16 09:59:14

标签: elasticsearch

我目前正在尝试将基于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)的所有文档。在条件状态= 1后生成过滤器并提升具有图像的文档。”

我一直在尝试使用一个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
            }
          }
        }
      ]
    }
  }
}

正如您所看到的,“信息”的必须条件缺失。

有没有人有解决方案?

非常感谢你。

**更新**

我更新了我的弹性搜索查询并删除了该功能评分。我的基本问题仍然存在。

8 个答案:

答案 0 :(得分:265)

  • OR 的拼写
  • AND 拼写为必须
  • NOR 拼写为 should_not

示例:

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

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

您还可以执行更复杂的OR版本,例如,如果您想要匹配至少3个中的3个,则可以在" should"下指定5个选项。并设置" minimum_should" 3。

感谢Glen Thompson和Sebastialonso找到我的筑巢之前的地方。

也感谢Fatmajk指出" term"成为"匹配"在ElasticSearch 6中。

答案 1 :(得分:55)

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

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

以下是查询:

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说,至少有一个应该声明必须为真。

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

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

玩得开心:)

答案 2 :(得分:19)

使用上面我得到

[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]

这对我有用

针对Elasticsearch 5.6.4 +

进行了更新
{
    "query": {
        "bool": {
            "must": [
                {"term": {"shape": "round"}},
                {"bool": {
                    "should": [
                        {"term": {"color": "red"}},
                        {"term": {"color": "blue"}}
                    ]
                }}
            ]
        }
    }
}

答案 3 :(得分:11)

当涉及到AND,OR或IN之类的简单查询时,ElasticSearch绝对是可怕的。但是,您可以采用一种聪明的方法,将查询作为SQL编写,然后使用此出色的在线工具将其转换为ElasticSearch语法:

SQL到ElasticSearch转换器

https://www.toolsbuzz.com/query-converter

稍后您可以感谢我:)

答案 4 :(得分:2)

我最近也不得不解决这个问题,经过大量的反复试验后,我想出了这个问题(在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 :(得分:2)

如果您使用的是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 :(得分:0)

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

must中,您需要添加要与AND一起使用的查询条件数组;在should中,您需要添加要与{{ 1}}。

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

答案 7 :(得分:0)

这是将多个布尔查询嵌套在一个外部布尔查询中的方法 使用Kibana,

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. must_not