Запрос строки запроса ES с отдельной проверкой уникального значения

У меня есть запрос строки запроса, в котором поиск выполняется по именам элементов из поля ввода мгновенного поиска

{
"query": {
    "query_string" : {
        "default_field" : "name",
        "query" : "'.$searchQuery.'"
    }
}
}

Однако я хотел бы включить поиск категорий элементов в один и тот же запрос, надеюсь, с тегами или разделенными каким-либо образом, чтобы их можно было переместить в верхнюю часть результатов во внешнем интерфейсе. Категории предметов находятся в отдельном поле, _source для отдельных предметов выглядит так,

                "_source": {
                "name": "Whatever Item Name",
                "category": "Whatever Category",

Таким образом, если поисковый ввод - «Что угодно *», он должен возвращать элементы с именем «Что угодно», но также отдельно возвращать список уникальных значений категорий, которые содержат «Что угодно» (не все элементы, имеющие «Какую категорию»). Таким образом, он должен возвращать элементы, имена которых совпадают, которые могут иметь любую категорию, а также доступные категории среди всех элементов по отдельности. Можно ли это объединить в один запрос?


person Oscar    schedule 19.11.2018    source источник


Ответы (1)


У вас есть несколько вариантов, но вот два, которые я бы попробовал в первую очередь.

Используйте один запрос с помеченными / именованными подзапросами. Как вы можете видеть ниже, в bool/should мы запрашиваем имена и категории, которые соответствуют some_input, с небольшим повышением категорий, поэтому они получают лучший рейтинг и всплывают в результатах. Кроме того, результаты имеют имена name_match или category_match, поэтому вы знаете, что это за совпадения. Возможно, вы захотите немного поиграть с усилением. Также вам может потребоваться отрегулировать размер, чтобы получить все ожидаемые результаты:

{
  "size": 20,
  "query": {
    "bool": {
      "should": [
        {
          "query": {
            "query_string": {
              "default_field": "name",
              "query": "some_input",
              "_name": "name_match"
            }
          }
        },
        {
          "match": {
            "category": {
              "query": "some_input",
              "boost": 2,
              "_name": "category_match"
            }
          }
        }
      ]
    }
  }
}

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

{
  "query": {
    "query_string": {
      "default_field": "name",
      "query": "some_input"
    }
  },
  "aggs": {
    "categories": {
      "filter": {
        "match": {
          "category": {
            "query": "some_input"
          }
        }
      },
      "aggs": {
        "categories": {
          "terms": {
            "field": "category",
            "size": 10
          }
        }
      }
    }
  }
}

ОБНОВЛЕНИЕ

Чтобы вычислить категории для всех данных, вы можете использовать _ 7_ вместо query:

{
  "post_filter": {
    "query_string": {
      "default_field": "name",
      "query": "some_input"
    }
  },
  "aggs": {
    "categories": {
      "filter": {
        "match": {
          "category": {
            "query": "some_input"
          }
        }
      },
      "aggs": {
        "categories": {
          "terms": {
            "field": "category",
            "size": 10
          }
        }
      }
    }
  }
}
person Val    schedule 20.11.2018
comment
Спасибо за подробное объяснение. Второй запрос - это именно то, что я искал. Однако может заставить его работать только для категорий, которые входят в число категорий в хитах. Может ли это работать для всех проиндексированных категорий, независимо от того, попали они в хиты или нет? - person Oscar; 21.11.2018
comment
Потрясающе, рад, что хелэпд! - person Val; 26.11.2018