Как отфильтровать запрос по значению поля

Я работаю с elasticsearch Query dsl и не могу найти способ выразить следующее:

Возвратите результаты, которые имеют поле "price" > min budget и имеют "цена" ‹ максимальный бюджет и имеют has_price=true, а также возвращают все результаты, которые имеют "has_price=false"

Другими словами, я хотел бы использовать фильтр диапазона только для результатов, для которых поле has_price установлено в true, в противном случае для результатов, в которых для has_price установлено значение false, фильтр не учитывается.

Вот отображение:

{
  "formations": {
    "mappings": {
      "properties": {
        "code": {
          "type": "text"
        },
        "date": {
          "type": "date",
          "format": "dd/MM/yyyy"
        },
        "description": {
          "type": "text"
        },
        "has_price": {
          "type": "boolean"
        },
        "place": {
          "type": "text"
        },
        "price": {
          "type": "float"
        },
        "title": {
          "type": "text"
        }
      }
    }
  }
}

person Souames    schedule 10.10.2019    source источник
comment
Вы можете показать отображение индекса?   -  person dejanmarich    schedule 10.10.2019
comment
@DejanMarić Хорошо, я только что добавил это   -  person Souames    schedule 10.10.2019


Ответы (1)


Следующий запрос объединяет 2 сценария как 2 предложения should в логическом запросе. А так как есть только предложения must, minimum_should_match будет равно 1, что означает, что хотя бы одно предложение должно совпадать:

Абстрактный фрагмент кода

GET formations/_search
{
  "query": {
    "bool": {
      "should": [
        { <1st scenario: has_price = false> },
        { <2nd scenario> has_price = true AND price IN budget_range}
      ]
    }
  }
}

Фрагменты фактического кода

# 1. Create the index and populate it with some sample documents

POST formations/_bulk
{"index": {"_id": 1}}
{"has_price": true, "price": 2.0}
{"index": {"_id": 2}}
{"has_price": true, "price": 3.0}
{"index": {"_id": 3}}
{"has_price": true, "price": 4.0}
{"index": {"_id": 4}}
{"has_price": false, "price": 2.0}
{"index": {"_id": 5}}
{"has_price": false, "price": 3.0}
{"index": {"_id": 6}}
{"has_price": false, "price": 4.0}

# 2. Query assuming min_budget = 2.0 and max_budget = 4.0

GET formations/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "filter": {
              "term": {
                "has_price": false
              }
            }
          }
        },
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "has_price": true
                }
              },
              {
                "range": {
                  "price": {
                    "gt": 2,
                    "lt": 4
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

# 3. Result Snippet (4 hits: 3 from 1st scenario & 1 from 2nd scenario)
"hits" : {
  "total" : {
    "value" : 4,
      "relation" : "eq"
    },
    ...

Не забудьте добавить Claus "minimum_should_match": 1 к вашему логическому запросу на случай, если вы добавите в свой логический запрос еще одно предложение, не связанное с необходимостью.

Дайте мне знать, если это ответит на ваш вопрос и решит вашу проблему.

person Daniel Schneiter    schedule 10.10.2019