首页 文章

elasticsearch bool query必须与OR结合使用

提问于
浏览
84

我目前正在尝试将基于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
            }
          }
        }
      ]
    }
  }
}

如您所见,缺少“信息”的必须条件 .

有没有人有办法解决吗?

非常感谢 .

更新

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

6 回答

  • 4
    • OR 拼写 should

    • AND 拼写为 must

    • 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指出“术语”在ElasticSearch 6中变得“匹配” .

  • 46

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

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

    这是查询:

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

    有乐趣的人:)

  • 0

    使用上面的我得到

    [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"}}
                        ]
                    }}
                ]
            }
        }
    }
    
  • 17

    当涉及简单查询(如AND,OR或IN)时,ElasticSearch绝对是可怕的 . 但是,您可以采用智能方式将查询编写为SQL,然后使用此优秀的在线工具将其转换为ElasticSearch语法:

    SQL to ElasticSearch converter

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

    您可以稍后感谢我 :)

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

    希望这有助于某人!

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

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

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

相关问题