Помогите мне понять моделирование mnesia (NoSQL)
В моем Поиске понимания Мнезии я все еще борюсь с мышлением в отношениях. Поэтому я поставил свою борьбу здесь и попрошу наилучшего способа их решения.
один-ко-многим-отношений
Скажем, у меня есть группа людей,
-record(contact, {name, phone}).
Теперь я знаю, что я могу определить, что телефон всегда будет сохранен в виде списка, поэтому у людей может быть несколько телефонных номеров, и я полагаю, что способ сделать это (не так ли? по-другому, скажем, найти имя для числа?).
много-ко-многим-отношения
теперь пусть предположим, что у меня есть несколько групп, в которые я могу поместить людей. Названия групп не имеют никакого значения, они просто имена; концепция "unix system groups" или "label". Наивно, я бы моделировал это членство как пролистник, например
{groups [{friends, bool()}, {family, bool()}, {work, bool()}]} %% and so on...
как поле внутри "контактной" записи сверху, например. Каков наилучший способ моделировать это в mnesia, если я хочу, чтобы вы могли быстро найти всех членов группы на основе имени группы, а также хотите, чтобы иметь возможность искать всю группу, в которой зарегистрирован человек? Я также мог бы просто моделировать это как список, содержащий только идентификаторы групп, конечно. Для использования с mnesia как лучше всего это смоделировать?
Извиняюсь, если этот вопрос глупо. Там много документации по mnesia, но в ней отсутствует (IMO) несколько хороших примеров для общего использования.
Ответы
Ответ 1
В первом примере рассмотрим эту запись:
-record(contact, {name, [phonenumber, phonenumber, ...]}).
contact
- это запись с двумя полями name
и phone
, где телефон представляет собой список телефонных номеров. Поскольку user425720 сказал, что имеет смысл хранить их как нечто иное, чем строки, если у вас есть экстремальные требования для небольшого пространства для хранения, например.
Теперь вот часть, которую трудно "получить" с магазинами с ключом: вам также нужно сохранить обратную связь. Другими словами, вам нужно что-то похожее на следующее:
-record(phone, {phonenumber, contactname}).
Если у вас есть слой в приложении для абстрагирования обработки базы данных, вы можете всегда добавлять/изменять записи телефона при добавлении/изменении контакта.
-
Во втором примере рассмотрим эти две записи:
-record(contact, {uuid, name, [group_id, group_id]}).
-record(group, {uuid, name, [contact_id, contact_id]}).
Самый простой способ - просто сохранить идентификаторы, указывающие на связанные записи. Поскольку у Mnesia нет концепции ссылочной целостности, это может стать несовместимым, если вы, например, удалите группу, не удаляя эту группу у всех пользователей.
Если вам нужно сохранить тип группы в записи контакта, вы можете использовать следующее:
-record(contact, {name, [{family, [group_id, group_id]}, {work, [..]}]}).
-
Ваша вторая проблема также может быть решена с помощью промежуточной записи, которую вы можете представить как "членство".
-record(contact, {uuid, name, ...}).
-record(group, {uuid, name, ...}).
-record(membership, {contact_uuid, group_uuid}). # must use 'bag' table type
Может быть любое количество записей "членства". Для каждой группы пользователей будет одна запись.
Ответ 2
Прежде всего, вы запрашиваете шаблоны дизайна хранилища ключей. Прекрасно.
Прежде чем я попытаюсь ответить на ваш вопрос, давайте проясним, что такое Mnesia. Это k-v DB, который включен в OTP. Поскольку он является родным, его очень удобно использовать в Erlang. Но будь осторожен. Это старая база данных с очень древними предположениями (например, распределение данных с линейным хешированием). Так что продолжайте, учитесь и играйте с ним, но для производства не торопитесь и просмотрите магазин NoSQL, чтобы найти лучшее для ваших нужд.
Пример @telephone. Не храните вещи в виде строк (list()) - это очень тяжело для GC. Я бы сделал пару полей, таких как phone_1:: < < binary → , phone_2:: < < binary → , phone_extra:: [< < binary → ] и построить индекс в наиболее часто встречающемся поле запроса. Также индикаторы mnesia сложны - когда node падает и поднимается, им нужно перестроить себя (это может занять очень много времени).
Пример @family. Это довольно сложно с плоским пространством имен. Вы можете играть с более сложными ключами. Может быть, создать отдельную таблицу для TheGroup и сохранить идентификаторы участников? Или у каждого члена есть идентификаторы групп, к которым он принадлежит (трудно поддерживать..). Если вы хотите узнать друзей, я бы выполнил какой-то контракт перед представлением данных (A является другом B, если B является другом) - этот подход справится с возможной согласованностью и конфликтами в данных.