Отфильтруйте документ, чтобы он соответствовал любому из двух полей во вложенном полеasticsearch - PullRequest
0 голосов
/ 06 марта 2019

У меня есть поле с именем теги в моем документе вasticsearch со следующей структурой.

tags = [
    {
        "id": 10,
        "related": [9, 8, 7]
    }
]

Теперь я запускаю фильтр со списком. например [10, 9]. Я хочу фильтровать только те документы, которые содержат все элементы в списке либо в id, либо в связанных. Если я ищу с [9, 8], вышеупомянутый документ должен быть возвращен. Если я ищу с [9, 12], вышеупомянутый документ не должен быть возвращен, так как 12 не присутствует ни в id, ни в связанном с ним.

Я пробовал с фильтром терминов, но он просто делает или. Существует ли какая-либо методика, которая может быть реализована для достижения вышеуказанной цели.

Далее, я хотел бы предоставить более высокий рейтинг документу, который содержит данные элементы в id, по сравнению с теми, которые содержат данные элементы в related.

1 Ответ

1 голос
/ 06 марта 2019

Анализ проблемы

Давайте разберем вашу проблему в следующих подзадачах:

  • (P1) Проверьте, присутствуют ли все термины, представленные в массиве, либо в tags.id, либо tags.related. Это может быть далее разложено на:
    • (P1.1) Проверьте, присутствует ли в all термины, указанные в массиве, в поле
    • (P1.2) Проверьте, распространяется ли all термины, представленные в массиве, на разные поля
  • (P2) Присвойте более высокий балл тем документам, имеющим любое из предоставленных условий, как tags.id

Решение

Чтобы решить (P1.1) , вы можете использовать запрос terms_set, доступный в Elasticsearch v6.6 (см. документация ).

Чтобы решить (P1.2) , я бы скопировал все значения tags.id и tags.related в новое настраиваемое поле с именем, например, tags.all. Это может быть достигнуто с помощью свойства copy_to следующим образом:

{
  "mappings": {
    "_doc": {
      "properties": {
        "tags": {
          "properties": {
            "id": { 
              "type": "long",
              "copy_to": "tags.all"
            },
            "related": { 
              "type": "long",
              "copy_to": "tags.all"
            }
          }
        }
      }
    }
  }
}

Затем, чтобы решить (P1) , вы можете выполнить свой запрос terms_set для tags.all. Например.,

{
  "query": {
    "terms_set": {
      "tags.all": {
        "terms": [ 9, 8 ],
        "minimum_should_match_script": {
          "source": "2"
        }
      }
    }
  }
}

Наконец, чтобы решить (P2) , вы можете создать логический запрос should, который включает (i) запрос terms_set, описанный выше, (ii) запрос terms против tags.id только, который имеет более высокий коэффициент усиления. То есть.,

{
  "query": {
    "bool": {
      "should": [
        {
          "terms_set": {
            "tags.all": {
              "terms": [ 9, 8 ],
              "minimum_should_match_script": {
                "source": "2"
              }
            }
          }
        },
        {
          "terms": {
            "tags.id": {
              "value": [ 9, 8 ],
              "boost": 2
            }
          }
        }
      ]
    }
  }
}
...