elasticsearch布尔查询组合必须具有OR



我目前正在尝试将一个基于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中使用布尔查询,但未能将布尔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
            }
          }
        }
      ]
    }
  }
}

如您所见,缺少infomust条件。

**更新**

我已经更新了我的弹性搜索查询,并去掉了那个函数得分。我的基本问题仍然存在。

  • OR拼写为
  • AND拼写为必须
  • NOR拼写为must_not

示例:

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

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

你也可以做更复杂的OR版本,例如,如果你想匹配5个选项中的至少3个,你可以在"下指定5个选项;应该";并设置一个";最小_应该"共3个。

感谢Glen Thompson和Sebastianoso找到了我以前不太适合筑巢的地方。

还感谢Fatmajk指出;术语";变成";匹配";在ElasticSearch版本6中。

我终于创建了一个查询,它正是我想要的:

已筛选的嵌套布尔查询。我不知道为什么没有记录下来。也许有人能告诉我?

以下是查询:

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语句必须为true。

这句话意味着,只要结果集中有一个文档包含has_image:1,它就会增加100倍。这将更改结果顺序。

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

玩得开心的家伙:)

这就是如何在一个外部布尔查询中嵌套多个布尔查询使用Kibana,

  • bool表示我们正在使用boolean
  • 必须用于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";比如

  1. 过滤器
  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

希望这能帮助到别人!

如果您使用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)"
    }
  }
}

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

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

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

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

最新更新