【问题标题】:Elasticsearch dsl OR query formationElasticsearch dsl OR 查询形成
【发布时间】:2020-02-20 21:42:47
【问题描述】:

我有多个文档的索引。文档包含以下字段:

  • 姓名
  • adhar_number
  • pan_number
  • acc_number

我想创建一个 elasticsearch dsl 查询。对于此查询,有两个输入可用,例如 adhar_number 和 pan_number。此查询应与 OR Condition 匹配。

示例:如果一个文档仅包含提供的 adhar_number,那么我也想要该文档。

我有一本包含以下内容的字典 (my_dict):

{
  "adhar_number": "123456789012",
  "pan_number": "BGPPG4315B"
}

我尝试如下:

from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search

es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
s = Search(using=es, index="my_index")
for key, value in my_dict.items():
   s = s.query("match", **{key:value})

print(s.to_dict())
response = s.execute()
print(response.to_dict())

它创建以下查询:

{
  'query': {
    'bool': {
      'must': [
        {
          'match': {
            'adhar_number': '123456789012'
          }
        },
        {
          'match': {
            'pan_number': 'BGPPG4315B'
          }
        }
      ]
    }
  }
}

上面的代码为我提供了 AND 条件 而不是 OR Condition 的结果。

请向我提出包含 OR 条件的好建议。

【问题讨论】:

    标签: python-3.x elasticsearch elasticsearch-dsl-py


    【解决方案1】:

    要修复 ES 查询本身,您需要做的就是使用“应该”而不是“必须”:

    {
      'query': {
        'bool': {
          'should': [
            {
              'match': {
                'adhar_number': '123456789012'
              }
            },
            {
              'match': {
                'pan_number': 'BGPPG4315B'
              }
            }
          ]
        }
      }
    }
    

    要在 python 中实现这一点,请参见the docs 中的以下示例。默认逻辑是 AND,但您可以将其覆盖为 OR,如下所示。

    查询组合查询对象可以使用逻辑组合 运营商:

    Q("match", title='python') | Q("match", title='django')
    # {"bool": {"should": [...]}}
    
    Q("match", title='python') & Q("match", title='django')
    # {"bool": {"must": [...]}}
    
    ~Q("match", title="python")
    # {"bool": {"must_not": [...]}} 
    

    当你多次调用 .query() 方法时,内部会使用 & 运算符:

    s = s.query().query() print(s.to_dict())
    # {"query": {"bool": {...}}}
    

    如果你想对查询表单有精确的控制,使用Q快捷键直接构造组合 查询:

    q = Q('bool',
        must=[Q('match', title='python')],
        should=[Q(...), Q(...)],
        minimum_should_match=1 ) s = Search().query(q)
    

    所以你想要类似的东西

    q = Q('bool', should=[Q('match', **{key:value})])
    

    【讨论】:

      【解决方案2】:

      您可以使用@ifo20 也提到的should。请注意,您很可能还想定义 minimum_should_match 参数:

      您可以使用 minimum_should_match 参数指定返回的文档必须匹配的 should 子句的数量或百分比。

      如果 bool 查询至少包含一个 should 子句且没有 must 或 filter 子句,则默认值为 1。否则,默认值为 0。

      {
        'query': {
          'bool': {
            'should': [
              {
                'match': {
                  'adhar_number': '123456789012'
                }
              },
              {
                'match': {
                  'pan_number': 'BGPPG4315B'
                }
              }
            ],
            "minimum_should_match" : 1
          }
        }
      }
      

      还要注意,should 子句会影响最终得分。我不知道如何避免这种情况,但您可能不希望这成为 OR 逻辑的一部分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 2018-10-17
        • 1970-01-01
        • 1970-01-01
        • 2022-12-15
        • 1970-01-01
        • 2021-11-15
        相关资源
        最近更新 更多