#node.js #elasticsearch #graphql
#node.js #elasticsearch #graphql
Вопрос:
Итак, у нас есть схема людей и схема проекта, обе из которых используются на отдельных страницах, где вы можете фильтровать результаты. Мы находимся на этапе, когда понимаем, что нам нужно фильтровать что-то вроде текущих проектов, но в списке ПОЛЬЗОВАТЕЛЕЙ. Однако данные для этого хранятся в проектах, и у нас возникают проблемы с поиском чистого способа перекрестных ссылок на схемы и фильтрации по вычисленному значению.
Например. Фильтровать список людей по проектам, которые в данный момент активны (т.е. текущее время).
Похоже, что в ES нет никакого способа сделать это — мой текущий вариант — объединить их во внешнем интерфейсе и выполнить там еще один «фильтр», но это кажется хакерским.
Отображение данных в списке пользователей не проблема, это фильтрация.
Кто-нибудь сталкивался с такой ситуацией раньше и как вы ее разрешали? Ценю любую информацию. Спасибо!
Ответ №1:
Если я правильно понимаю, у вас есть два отдельных индекса для людей и проектов.
К сожалению, единственный способ сделать все правильно — это денормализовать ваши данные в Elasticsearch и включить проекты в список пользователей.
Комментарии:
1. Да, я так и думал, но мой ведущий считает, что это плохая идея. Ну что ж, я пытался. Спасибо!
2. Я имею в виду, что в зависимости от вашего размера вы, вероятно, могли бы решить это на уровне вашего приложения, но это ненадежно и будет медленным по сравнению с денормализованными данными. 🙂
Ответ №2:
Вы также можете использовать отношения родитель-потомок.
Пожалуйста, прочтите эти отличные сообщения в блоге: https://rockset.com/blog/can-i-do-sql-style-joins-in-elasticsearch / а затем родительско-дочернее моделирование в Elasticsearch https://blog.mimacom.com/parent-child-elasticsearch / По предыдущей ссылке показаны примеры в ElasticSearch 5.6 и 6. Я приведу примеры, которые работают в ES 7:
Согласно сообщению:
Существует четыре распространенных подхода к управлению данными в Elasticsearch:
Денормализация, объединения на стороне приложения, вложенные объекты, отношения родитель-потомок
- Взаимно однозначные отношения: сопоставление объектов
- Отношения «один ко многим»: вложенные документы и модель «родитель-потомок»
- Отношения «многие ко многим»: денормализация и объединения на стороне приложения
Проблемы с родительско-дочерними отношениями
Запросы являются более дорогостоящими и требуют больше памяти из-за операции объединения. Для родительско-дочерних конструкций существуют накладные расходы, поскольку они представляют собой отдельные документы, которые должны быть объединены во время запроса. Необходимо убедиться, что родительский элемент и все его дочерние элементы существуют в одном сегменте. Хранение документов с родительско-дочерними отношениями связано со сложностью реализации.
Я приведу пример, готовый к выполнению в ES 7
curl -XDELETE "localhost:9200/project"
curl -XPUT "localhost:9200/project"
-H 'Content-Type: application/json'
-d'{
"settings": {
"number_of_shards": 1, "number_of_replicas": 0
},
"mappings": {
"properties": {
"project": { "type": "text" },
"people": { "type": "text" },
"active": { "type": "boolean" },
"project_relations": {
"type": "join",
"relations": {
"project": "people"
}
}
}
}
}'
curl -XPUT "localhost:9200/project/_bulk"
-H 'Content-Type: application/json'
-d'
{"index":{"_id":1}}
{"name":"ElasticSearch upgrade","project_relations":{"name":"project"}, "active": true}
{"index":{"_id":2}}
{"name":"Website","project_relations":{"name":"project"}, "active": true}
{"index":{"_id":3}}
{"name":"SQL Server migration","project_relations":{"name":"project"}, "active": false}
'
curl -XPUT "localhost:9200/project/_doc/4?routing=1"
-H 'Content-Type: application/json'
-d'
{"people":"Evaldas Buinauskas","project_relations":{"name":"people","parent":1}}
'
curl -XPOST "localhost:9200/project/_doc/5?routing=1"
-H 'Content-Type: application/json'
-d'
{"people":"xynon","project_relations":{"name":"people","parent":1}}
'
Маршрутизация должна соответствовать идентификатору проекта
curl -XPOST "localhost:9200/project/_doc/6?routing=2"
-H 'Content-Type: application/json'
-d'
{"people":"Harry scherer","project_relations":{"name":"people","parent":2}}
'
curl -XPOST "localhost:9200/project/_doc/7?routing=2"
-H 'Content-Type: application/json'
-d'
{"people":"Darrel Simon","project_relations":{"name":"people","parent":2}}
'
curl -XPOST "localhost:9200/project/_doc/8?routing=3"
-H 'Content-Type: application/json'
-d'
{"people":"Juan Carlos Alafita","project_relations":{"name":"people","parent":3}}
'
Поиск людей, работающих над обновлением ElasticSearch, и проект активен
curl -XGET "localhost:9200/project/_search"
-H 'Content-Type: application/json'
-d'
{
"query": {
"has_parent": {
"parent_type": "project",
"query": { "bool": {"must": [ {"match": { "active": true } }, {"match": { "name": "ElasticSearch upgrade" } } ] }}
}
}
}' | jq
Результаты:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "project",
"_type": "_doc",
"_id": "4",
"_score": 1,
"_routing": "1",
"_source": {
"people": "Evaldas Buinauskas",
"project_relations": {
"name": "people",
"parent": 1
}
}
},
{
"_index": "project",
"_type": "_doc",
"_id": "5",
"_score": 1,
"_routing": "1",
"_source": {
"people": "xynon",
"project_relations": {
"name": "people",
"parent": 1
}
}
}
]
}
}
Поиск людей, работающих над миграцией SQL Server, и проект неактивен
curl -XGET "localhost:9200/project/_search"
-H 'Content-Type: application/json'
-d'
{
"query": {
"has_parent": {
"parent_type": "project",
"query": { "bool": {"must": [ {"match": { "active": false } }, {"match": { "name": "SQL Server migration" } } ] }}
}
}
}
' | jq
curl -XGET "localhost:9200/project/_search"
-H 'Content-Type: application/json'
-d'
{
"query": {
"has_parent": {
"parent_type": "project",
"query": { "match_all": {} }
}
}
}'