Elasticsearch dsl ИЛИ формирование запроса

У меня есть индекс с несколькими документами. Документ содержит следующие поля:

  • название
  • adhar_number
  • pan_number
  • acc_number

Я хочу создать DSL-запрос Elassearch. Для этого запроса доступны два входа, такие как adhar_number и pan_number. Этот запрос должен соответствовать ИЛИ условию для этого.

Пример: если один документ содержит только предоставленный номер 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.

Пожалуйста, предложите мне хорошие предложения, чтобы включить или условие.

1 ответ

Чтобы исправить сам запрос ES, все, что вам нужно сделать, это использовать "must" вместо "must":

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

Чтобы добиться этого в Python, посмотрите следующий пример из документации. Логика по умолчанию - И, но вы можете переопределить ее ИЛИ, как показано ниже.

Комбинация запросов Объекты запросов можно объединять с помощью логических операторов:

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

Вы можете использовать should как также упоминается @ifo20. Обратите внимание, что вы, скорее всего, не хотите определять minimum_should_match а также параметры:

Вы можете использовать параметр minimum_should_match, чтобы указать количество или процентное соотношение возвращаемых документов, которые должны совпадать.

Если запрос типа bool включает хотя бы одно предложение should и никаких предложений must или filter, значение по умолчанию равно 1. В противном случае значение по умолчанию равно 0.

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

Также обратите внимание, что предложение следует вносить в окончательную оценку. Я не знаю, как этого избежать, но вы можете не захотеть, чтобы это было частью логики ИЛИ.

Другие вопросы по тегам