Сортировка родительских документов на основе лучшего (соответствующего) значения вложенного поля с помощью Elasticsearch - PullRequest
1 голос
/ 09 мая 2020

Версия Elasticsearch : 7.6.2

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

PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "description": {
        "type": "text"
      },
      "variants": {
        "type": "nested",
        "include_in_parent": true,
        "properties": {
          "price": {
            "type": "double"
          },
          "tags": {
            "type": "text"
          }
        }
      }
    }
  }
}

PUT /products/_doc/1?refresh
{
    "name": "Product Pizza",
    "description": "Product Pizza Description",
    "variants": [
        { "price": 100, "tags": ["capri", "small", "noketchup"] },
        { "price": 110, "tags": ["capri", "medium", "ketchup"] },
        { "price": 300, "tags": ["capri", "medium", "noketchup"] },
        { "price": 210, "tags": ["vege", "medium", "ketchup"] },
        { "price": 220, "tags": ["vege", "medium", "noketchup"] },
        { "price": 330, "tags": ["vege", "large", "ketchup"] }
    ]
}


PUT /products/_doc/2?refresh
{
  "name": "Product Towel",
  "description": "Product Towel Description",
  "variants": [
    { "price": 50, "tags": ["blue", "small"] },
    { "price": 60, "tags": ["blue","medium"] },
    { "price": 70, "tags": ["blue","large"] },
    { "price": 55, "tags": ["red","small"] },
    { "price": 65, "tags": ["red","medium"] },
    { "price": 75, "tags": ["red","large"] }
  ]
}


GET /products/_search
{
  "track_scores": true,
  "query": {
    "nested": {
      "path": "variants",
      "inner_hits": {
        "size": 10
      },
      "query": {
        "multi_match": {
          "query": "vege medium",
          "operator": "or",
          "fields": [
            "variants.tags"
          ]
        }
      }
    }
  },
  "sort": [
    {
      "variants.price": {
        "mode": "min",
        "nested": {
          "filter": {
            "multi_match": {
              "query": "vege medium",
              "operator": "or",
              "fields": [
                "variants.tags"
              ]
            }
          },
          "path": "variants"
        },
        "order": "asc"
      }
    }
  ]
}

Мне нужно как-то добиться наилучшего сопоставив вложенный результат, а затем возьмите поле цены из этого вложенного варианта.

  1. При сортировке по минимальной цене сортировка должна вернуть 210 для первого продукта и 60 для второго продукта
    • Соответствие оба тега "vege" "medium"
  2. При сортировке по максимальной цене сортировка должна возвращать 220 для первого продукта и 65 для второго продукта
    • Соответствует одному тегу " medium "

Я пробовал несколько вещей: 1. Использование" и "вместо" или "для multi_match, но затем второй продукт исключается из результатов. 2. Использование max_children для сортировки вложенных элементов, но оно берет только первое вложенное значение из массива (после фильтрации оно не сортирует их по количеству очков). 3. Я проверил, можно ли отсортировать вложенные варианты по количеству очков перед запуском max_children, по-видимому, нет.

Любое предложение приветствуется, это не окончательная структура, поэтому любые идеи по изменению структуры также приветствуются.

Как это достигается, может быть, с помощью скриптов?

...