Какой более идиоматический вариант в Datomic Land для этой схемы?

У меня есть вопрос относительно того, какая схема более идиоматична для Datomic.

Допустим, у нас есть объекты User, Post и Topic.

Post может принадлежать Topic, User и другим Post (ответы). Теперь, я должен,

а) Создать атрибут :posts, который представляет собой просто список Post, и внедрить его в каждую сущность, которая требует ссылки на количество Post?

or

b) Установить более явные отношения, например, чтобы Post имел атрибут :post/author, который является ссылкой на пользователя, и, возможно, атрибут :post/belongs-to, который может ссылаться либо на Topic, либо на другой Post?

Наблюдения: Если я делаю b, я получаю больше семантических отношений. Я могу, например, сделать (:post/_author user-entity), который лучше описывает характер их магазина отношений, чем (:posts user-entity) (поскольку, что означает, что User имеет :posts? Это Users избранные Posts, авторские Posts или что?)

Еще один побочный эффект b заключается в том, что я могу создать новый Post, не изменяя никакой другой объект. Если я делаю a, мне нужно создать Post, а также вставить его в атрибут :posts User, что требует двух операций вместо одной.

Однако у меня есть ощущение, что a может быть более идиоматичным способом сделать это. Кажется, например, что было бы легче увидеть, как список атрибута :posts изменился с течением времени, если я захочу это сделать, если User ссылается на :posts, а не имеет Post ссылку User через атрибут :post/author.

Что было бы предпочтительнее и почему?


person Henrik    schedule 19.11.2013    source источник


Ответы (2)


Ваш вариант (b) по сути является идиоматичным и единственным способом использования datomic.

Вся схема datomic кодируется только как значения, которые может принимать атрибут в структуре datom объект-атрибут-значение (EAV).

См. http://docs.datomic.com/schema.html — ключевое предложение, взятое из документов:

Каждая база данных Datomic имеет схему, описывающую набор атрибутов, которые могут быть связаны с сущностями. Схема определяет только характеристики самих атрибутов. Он не определяет, какие атрибуты могут быть связаны с какими объектами.

Сущности сами по себе очень абстрактны (и внутренне представляют собой просто числа), все интересные свойства сущностей закодированы как утверждения значений атрибутов. Сущности не типизированы! Вы создаете семантику объекта с помощью атрибутов, которые вы утверждаете для него, таких как :user/firstname, :post/title, :post/content, :topic/description и т. д. Вот почему вы действительно хотите использовать пространство имен для атрибутов.

Особым случаем этого является тип атрибута :db.type/ref, где значение «V» в EAV само по себе является другим объектом. Именно это создает семантические ассоциации между сущностями. Вы даете каждому атрибуту «имя» (в виде :db/ident), чтобы понять, что на самом деле означает соединение E‹->E. Таким образом, у вас может быть атрибут :db.type/ref с :db/ident ":post/author".

Обратите внимание, что все атрибуты :db.type/ref по своей сути являются двунаправленными, поэтому, если Eu — это объект, представляющий пользователя, а Ep — объект, представляющий сообщение, то следующие эквивалентны как при создании данных, так и при запросе:

[Ep :post/author  Eu]
[Eu :post/_author Ep]

Все отношения сущностей, являющиеся просто дополнительными утверждениями атрибутов, действительно гибкие. Если позже вы захотите добавить концепцию избранных постов, это просто еще один атрибут :db.type/ref. Создайте его с помощью :db/ident, такого как «:user/favorites», и установите связи между уже существующими пользователями и сообщениями (которые имеют разные пользовательские объекты в качестве авторов).

[aUser :user/favorites somePost]

Не существует понятия атрибутов, оцениваемых коллекцией, поэтому то, что вы предлагаете в (a), не может быть правильно выражено в datomic. Вы должны использовать запрос для агрегирования сообщений. Последующее удаление будет моделироваться отзывом самой сущности. Такой отозванный пост останется видимым в истории базы данных.

Это создает проблему, как указать порядок списков сущностей. Вам нужно либо использовать «естественный» порядок, такой как дата публикации (захваченная либо в datomic-транзакции, либо как явный атрибут публикации), либо использовать явное упорядочение на основе значения атрибута, например, через :post/up- числовой атрибут голосов.

Если вам нужна семантическая группировка сущностей, где «подсущности» имеют только смысл и существуют только как часть чего-то большего, например. объекты позиции в заказе, а затем см. компоненты datomic.

person Alex Stoddard    schedule 30.12.2013
comment
Не существует понятия атрибутов, оцениваемых коллекцией, поэтому то, что вы предлагаете в (a), не может быть правильно выражено в datomic. Я не понимаю эту часть — разве не этим занимается :db.cardinality/many? - person rcrogers; 15.12.2014
comment
@rcrogers - С моей стороны нет преувеличения. :db.cardinatlity/many позволяет выражать набор значений. Таким образом, атрибут может быть многозначным, но только с установленной семантикой, атрибут не может напрямую представлять другие типы коллекций. - person Alex Stoddard; 15.12.2014
comment
Вот почему вы действительно хотите использовать пространство имен для атрибутов. Как насчет использования одного и того же атрибута в разных сущностях? Есть ли какие-либо ограничения или это только соглашение об именах? - person tuscland; 22.04.2016
comment
@tuscland - Нет никаких ограничений на то, какие атрибуты вы связываете. Пространство имен атрибутов - это просто соглашение об именах, но оно предотвращает случайную перегрузку семантики атрибута, например. название используется для связывания как названий книг, так и титула автора (мистер/миссис и т. д.) - person Alex Stoddard; 22.04.2016

Я думаю, что это зависит в основном от ваших моделей доступа. Если каждый раз, когда вы обращаетесь к объекту, который может вставлять связанные записи, вам действительно нужны эти записи, имеет смысл встроить их (a). Если большую часть времени вы обращаетесь к ним по отдельности, возможно, будет лучше разделить их (b).

Или вы можете сделать и то, и другое (c), рассматривая отдельный объект Post как канонический, а встроенный в различные объекты как кэшированные версии. Таким образом, вам нужен скрипт/пакет, который обновляет встроенные сообщения каждый раз, когда обновляется каноническая версия. Это упрощает чтение, так как информация всегда присутствует, но запись усложняется, так как вам нужно синхронизировать их самостоятельно. Также этот паттерн можно использовать только в том случае, если вы можете смириться с некоторым несоответствием между канонической и встроенной версиями и задержка ресинхронизации для вас не критична.

Примечание: этот совет не имеет отношения конкретно к Datomic, это методы, заимствованные из мира NoSQL, и я ни в коем случае не являюсь специалистом.

person DjebbZ    schedule 21.11.2013
comment
Спасибо! Очень ценится. Это хорошая информация, но я также ищу ответ, специфичный для Datomic. - person Henrik; 02.12.2013