От многих до многих отношений в Firebase
У меня есть база данных Firebase. У меня есть компании и подрядчики. Подрядчик может работать более чем в одной Компании, и у Компании может быть несколько Подрядчиков. Это очень много отношения ко многим. Я хочу иметь возможность ответить на вопросы о компаниях и подрядчиках:
- Для Компании, являющихся действующими Подрядчиками.
- Для Подрядчика, для каких компаний они работают.
Каковы альтернативы для структурирования данных в firebase?
Ответы
Ответ 1
Самопомощь - это действительно один из способов моделирования этого. Это, вероятно, самый прямой эквивалент того, как вы моделируете это в реляционной базе данных:
- подрядчики
- компании
- companyAndContractorsAssignment (таблица соединений "многие-ко-многим" )
Альтернативой может быть использование 4 узлов верхнего уровня:
- подрядчики
- компании
- companyContractors
- contractorCompanies
Последние два узла будут выглядеть так:
companyContractors
companyKey1
contractorKey1: true
contractorKey3: true
companyKey2
contractorKey2: true
contractorCompanies
contractorKey1
companyKey1: true
contractorKey2
companyKey2: true
contractorKey3
companyKey1: true
Эта двунаправленная структура позволяет вам как искать "подрядчиков для компании", так и "компании для подрядчика", причем ни один из них не должен быть запросом. Это должно быть быстрее, особенно когда вы добавляете подрядчиков и компании.
Требуется ли это для вашего приложения, зависит от используемых вами прецедентов, размеров данных, которые вы ожидаете, и многое другое.
Рекомендуемое чтение Моделирование данных NoSQL и просмотр Firebase для разработчиков SQL. Этот вопрос также был показан в эпизоде серии youtube #AskFirebase.
Обновление (2017016)
Кто-то отправил следующий вопрос, который ссылается здесь о поиске фактических предметов из узлов "подрядчиков" и "компаний". Вам нужно будет получить их по одному, поскольку Firebase не имеет эквивалента SELECT * FROM table WHERE id IN (1,2,3)
. Но эта операция не так медленна, как вы думаете, потому что запросы конвейерны по одному соединению. Подробнее об этом читайте здесь: Ускорьте выборку сообщений для моего приложения в социальной сети, используя запрос вместо повторного наблюдения за одним событием.
Ответ 2
После дальнейших исследований я попытаюсь ответить на свой вопрос. Я рассмотрел ряд других сообщений, и одним из решений проблемы "многие-ко-многим" является сохранение списка "Подрядчиков" в объекте "Компания" и сохранение списка "Ключи компании" в каждом объекте-подрядчике. Это проиллюстрировано на примере ниже.
companies : {
companyKey1 : {
name : company1
...
contractors : {
contractorKey1 : true,
contractorKey3 : true
}
}
companyKey2 : {
name : company2
...
contractors : {
contractorKey2 : true,
}
}
}
contrators : {
contractorKey1 : {
name : bill
...
companies : {
companyKey1 : true
}
}
contractorKey2 : {
name : steve
...
companies : {
companyKey1 : true
}
}
contractorKey3 : {
name : jim
...
companies : {
companyKey2 : true
}
}
}
Эта организация "работает" в том смысле, что на вышеупомянутые вопросы можно ответить. Но недостатком этого решения является то, что есть два списка для поддержки, когда изменения Подрядчика/Компании меняются. Было бы лучше, если бы был способ представить эту информацию в одном списке.
Думаю, я придумал лучшее решение. Решение заключается в создании третьего списка, в дополнение к компаниям и подрядчикам, называемым companyAndContractorAssignment. Элементы этого списка будут представлять собой отношения между одним подрядчиком и компанией. Его содержимым будет пара полей, подрядчикKey и компанияKey. Затем мы можем исключить список подрядчиков внутри компании и список компаний в рамках подрядчика. Эта альтернативная структура представлена ниже. Обратите внимание, что в объекте компании нет списка подрядчиков, и нет списка компаний с объектом подрядчика.
companies : {
companyKey1 : {
name : company1
...
}
companyKey2 : {
name : company2
...
}
}
contrators : {
contractorKey1 : {
name : bill
...
}
contractorKey2 : {
name : steve
...
}
contractorKey3 : {
name : jim
...
}
}
companyAndContractorsAssignment : {
key1 : {
contractorKey1 : true,
companyKey1: true,
}
key2 : {
contractorKey3 : true,
companyKey1: true,
}
key3 : {
contractorKey2 : true,
companyKey2: true,
}
Эта альтернативная структура позволяет ответить на вопросы, используя запрос orderByChild/equalTo на companyAndContractorsAssignment, чтобы найти все компании для подрядчика или всех подрядчиков для компании. И теперь есть только один список для поддержки. Я думаю, что это лучшее решение для моих требований.