Поиск по нескольким индексам в elastica

Я ищу способ поиска по нескольким индексам одновременно с помощью Elastica.

У меня есть индекс products и индекс user.

products содержит {product_id, product_name, price}, а user содержит {product_id, user_name, date}. Зная, что product_id в обоих случаях одинакова, в products каждый products_id уникален, а в user — нет, поскольку пользователь может покупать один и тот же продукт несколько раз.

В любом случае, я хочу автоматически получать цену продукта из индекса products при поиске по индексу user.

Я знаю, что мы можем искать по нескольким индексам так (поправьте меня, если я ошибаюсь):

$search = new \Elastica\Search($client);
$search->addIndex('users')
        ->addType('user')
        ->addIndex('products')
        ->addType('product');

Но проблема в том, что когда я пишу агрегацию, например, для products_id, а затем создаю новый запрос с некоторыми фильтрами:

$products_agg = new \Elastica\Aggregation\Terms('products_id');
$products_agg->setField('products_id')->setSize(0);

$query = new \Elastica\Query();
$query->addAggregation($products_agg);
$query->setQuery($bool);

$search->setQuery($query);

Как эластика узнает, в каком индексе искать? Как я могу связать этот products_id с другим индексом?


person Islam Elshobokshy    schedule 10.10.2018    source источник


Ответы (4)


Библиотека Elastica поддерживает Multi Search API, API множественного поиска позволяет выполнять несколько поисковых запросов в рамках одного API. Конечная точка для него — _msearch.

Формат запросов аналогичен массовому API. Первая строка — это часть заголовка, которая включает в себя индекс/индексы для поиска. Вторая строка включает типичные запросы тела поиска.

{"index" : "products", "type": "products"}
{"query" : {"match_all" : {}}, "from" : 0, "size" : 10} // write your own query to get price
{"index" : "uesrs", "type" : "user"}
{"query" : {"match_all" : {}}} // query for user

Проверьте тестовый пример в Multi/SearchTest.php чтобы узнать, как использовать.

person Gasol    schedule 22.10.2018

В основном вы хотите объединить два индекса на основе общего поля, как в sql.

Что вы можете сделать, так это смоделировать данные в одном и том же индексе, используя join datatype.

https://www.elastic.co/guide/en/elasticsearch/reference/master/parent-join.html

Индексировать все документы в одном индексе,

  • Сделать все документы на товар - родительскими.
  • Сделать все пользовательские документы дочерними

И использовать агрегации и запросы родитель-потомок

https://www.elastic.co/guide/en/elasticsearch/reference/master/parent-join.html#_parent_join_queries_and_aggregations

ПРИМЕЧАНИЕ: убедитесь в влиянии сопоставления родитель-потомок на производительность https://www.elastic.co/guide/en/elasticsearch/reference/master/parent-join.html#_parent_join_and_performance

Еще одна вещь, которую вы можете сделать, предоставить всю информацию о продукте каждому покупающему его пользователю.

Но это может излишне тратить ваше пространство и не является хорошей практикой в ​​​​соответствии с правилами данных.

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

person gaurav9620    schedule 10.10.2018
comment
Спасибо за ваш ответ! :) Я думаю, что может быть более простой способ сделать это. Я также не уверен, что этот тип данных существует в моей версии elastica. - person Islam Elshobokshy; 10.10.2018
comment
Какую версию эластичного поиска вы используете? - person gaurav9620; 10.10.2018
comment
Я использую версию 1.6.2 - person Islam Elshobokshy; 11.10.2018
comment
В вашем случае это сопоставление родитель-потомок с данными двух типов в одном индексе в разных типах. Или же вы можете дублировать данные - person gaurav9620; 11.10.2018

вы можете попробовать следующее: 1- именовать индексы с определенным именем, например следующим

myFirstIndex-myProjectName
mySecIndex-myProjectName
myThirdIndex-myProjectName

и так далее.

2- это дает мне возможность использовать * в поле индексов для поиска, потому что он принимает подстановочные знаки, поэтому я могу выполнять поиск по нескольким полям, подобным этому, с помощью инструментов разработчика kibana.

GET *-myProjectName/_search
{
  "_source": {
    "excludes": [ "*" ]
  },
  "query": { "match_all": {} },
}

это будет искать по каждому индексу, включая -myProjectName.

person Mohamed Assem    schedule 16.10.2018
comment
Я ищу ответ Elastica, но спасибо за ваш ответ. - person Islam Elshobokshy; 17.10.2018

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

Другой вариант — добавить цену в пользовательский индекс. Иногда приходится жертвовать небольшим пространством ради удобства использования.

person ZiadM    schedule 18.10.2018
comment
Спасибо за ваш ответ. You can't query two indices with different mappings источник, пожалуйста? - person Islam Elshobokshy; 19.10.2018
comment
Также то, что я прошу, возможно в Elasticsearch наверняка (curl -H "Content-Type: application/json" -X POST 'elasticsearchServer.com/products,user/_search' --data '{"query":{"match_all":{}}}'), поэтому мой вопрос в том, как это сделать с помощью Elastica. - person Islam Elshobokshy; 19.10.2018
comment
Да, вы правы, может быть, мой ответ не очень ясен. Из вашего вопроса я понял, что вы пытаетесь объединить индексы, что лучше сделать, добавив поля продуктов внутри заказов, тем самым пожертвовав пространством. - person ZiadM; 19.10.2018