Как хранить реляционные данные в asticsearch
Какие есть варианты хранения реляционных данных в asticsearch. Я знаю следующие подходы
Вложенный объект:- Я не хочу хранить данные во вложенном формате, потому что я хочу обновить один документ без изменения другого документа, и если я использую вложенный объект, то в родительских документах будут повторяться дочерние данные.
Parent-child:- Я не хочу хранить данные в одном индексе, но для использования Parent-child данные должны присутствовать в одном индексе (разных типов). Я знаю, что это ограничение будет снято в будущем выпуске, как упомянуто в проблеме https://github.com/elastic/elasticsearch/issues/15613, но я хочу решение, которое должно работать с версией 5.5.
Есть ли какой-то другой подход, кроме как выше?
3 ответа
Вложенный объект является идеальным подходом для этого. Не будет повторения дочерних объектов в родительском документе, если вы обновите дочерние объекты правильно. Я использую тот же подход для одного из моих вариантов использования, где мне нужно поддерживать реляционные данные отношения Мастер-Ребенок один-ко-многим. Я написал сценарий Painless для Update API для добавления и обновления существующих вложенных дочерних объектов в родительском документе без создания дубликатов или повторяющихся записей.
Обновленный ответ:
Ниже приведена структура документа вложенного типа "родитель-потомок" со встроенными документами вложенного типа "потомки".
{
"parent_id": 1,
"parent_name": "ABC",
"parent_number": 123,
"parent_addr": "123 6th St. Melbourne, FL 32904"
"childs": [
{
"child_id": 1,
"child_name": "PQR",
"child_number": 456,
"child_age": 10
},
{
"child_id": 2,
"child_name": "XYZ",
"child_number": 789,
"child_age": 12
},
{
"child_id": 3,
"child_name": "QWE",
"child_number": 234,
"child_age": 16
}
]
}
Отображение будет как показано ниже:
PUT parent/
{
"parent": {
"mappings": {
"parent": {
"properties": {
"parent_id": {
"type": "long"
},
"parent_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"parent_number": {
"type": "long"
},
"parent_addr": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"child_tickets": {
"type": "nested",
"properties": {
"child_id": {
"type": "long"
},
"child_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"child_number": {
"type": "long"
},
"child_age": {
"type": "long"
}
}
}
}
}
}
}
}
В RDMS обе эти сущности (родительская, дочерняя) представляют собой две разные таблицы с отношением Один-ко-многим между Родителем -> Дочерним. Идентификатор родителя является внешним ключом для строки ребенка. (идентификатор должен для обеих таблиц)
Теперь в Elasticsearch, чтобы проиндексировать родительский документ, у нас должен быть идентификатор для его индексации, в данном случае это parent_id. Индекс Запрос родительского документа (parent_id - это идентификатор, о котором я говорил, и индексировать документ с идентификатором (_id) = 1):
POST parent/parent/1
{
"parent_id": 1,
"parent_name": "ABC",
"parent_number": 123,
"parent_addr": "123 6th St. Melbourne, FL 32904"
}
Теперь добавляем child(s) к родителю. Для этого вам потребуется дочерний документ, который должен иметь дочерний идентификатор и родительский идентификатор. Чтобы добавить ребенка, родительский идентификатор должен. Ниже приведен запрос на обновление для добавления новых дочерних элементов или обновления уже существующих дочерних элементов.
POST parent/parent/1/_update
{
"script":{
"lang":"painless",
"inline":"if (!ctx._source.containsKey(\"childs\")) {
ctx._source.childs = [];
ctx._source.childs.add(params.child);
} else {
int flag=0;
for(int i=0;i<ctx._source.childs.size();i++){
if(ctx._source.childs[i].child_id==params.child.child_id){
ctx._source.childs[i]=params.child;
flag++;
}
}
if(flag==0){
ctx._source.childs.add(params.child);
}
}",
"params":{
"child":{
"child_id": 1,
"child_name": "PQR",
"child_number": 456,
"child_age": 10
}
}
}
}
Дать ему шанс. Ура!
Позвольте мне знать, если вам нужно что-нибудь еще.
Есть еще два подхода: денормализация и запуск нескольких запросов для объединений.
Денормализация потребляет больше места и увеличивает время записи, но вам просто нужно выполнить один запрос для извлечения ваших данных, следовательно, время чтения улучшится. Поскольку вы не хотите хранить данные в одном индексе, объединение может помочь вам.
Существует четыре механизма, которые можно использовать для обеспечения поддержки моделирования реляционных данных. У каждого есть свои плюсы и минусы, что делает их полезными в разных ситуациях... вот краткое изложение:
Внутренний объект
- Легко, быстро, производительно
- Применимо только при сохранении отношений один к одному
- Нет необходимости в специальных запросах
Вложенный
- Вложенные документы хранятся в одном и том же блоке Lucene, что повышает производительность чтения/запроса. Чтение вложенного документа происходит быстрее, чем эквивалентного родителя/дочернего документа.
- Обновление одного поля во вложенном документе (родительском или вложенном дочернем) заставляет ES переиндексировать весь вложенный документ. Это может быть очень дорого для больших вложенных документов.
- "Перекрестные ссылки" вложенных документов невозможны
- Лучше всего подходит для данных, которые не меняются часто
Родитель/Ребенок
- Потомки хранятся отдельно от родителя, но перенаправляются в тот же шард. Таким образом, родительские/дочерние элементы немного менее производительны при чтении/запросе, чем вложенные.
- Сопоставления родитель/потомок имеют дополнительные накладные расходы на память, поскольку ES поддерживает список соединений в памяти.
- Обновление дочернего документа не влияет на родительский или любые другие дочерние документы, что потенциально может сэкономить много времени при индексировании больших документов.
- Сортировка/оценка может быть затруднена с использованием родительского/дочернего элементов, поскольку
- Операции Child/Has Parent иногда могут быть непрозрачными
Денормализация
- Вы сами управляете всеми отношениями!
- Самая гибкая, самые административные накладные расходы
- Может быть более или менее производительным в зависимости от вашей настройки
Для получения дополнительной информации перейдите по ссылке: https://www.elastic.co/blog/managing-relations-inside-elasticsearch .