Должен ли я моделировать это как дерево или как реляционный в MongoDB? - PullRequest
1 голос
/ 04 марта 2020

Мне нужно создать модель данных, которая имеет рекурсивные отношения, чтобы у каждого пользователя было два дочерних пользователя, а у каждого дочернего пользователя есть еще два дочерних пользователя. Такое поведение многократно повторяется при выращивании дерева. Я хочу использовать MongoDB в качестве базы данных. Я читал, что не рекомендуется помещать большой набор узлов в документ, поэтому я думал создать модель как реляционную модель или использовать другую базу данных для достижения этой цели. Что вы мне порекомендуете?

1 Ответ

1 голос
/ 04 марта 2020

Я бы сказал, что это действительно зависит от ваших шаблонов доступа к данным. Вы можете рассмотреть (как минимум) два сценария ios

# 1 Один большой документ

Это дает вам наилучшую производительность при чтении - вы просто запрашиваете по идентификатору или любому другому поле родительского уровня. Это было бы рекомендовано для простого доступа к данным, такого как получение всего дерева, обновление всего дерева как единой бизнес-операции. Недостатком является то, что запросы дочерних документов и их обновление становятся более сложными (но все же возможными - фильтры массивов ). Еще одна вещь, которую вы должны иметь в виду, это то, что MongoDB имеет ограничение в 16 МБ для одного размера документа. Это много, но вам нужно знать, как далеко может вырасти ваше дерево.

# 2 «Реляционный» способ

Вы можете хранить несколько документов в одной коллекции, и каждый из них может указывать на своего родителя. :

{
    _id: 1,
    name: "root",
    parent: null    
},
{
    _id: 2,
    name: "child",
    parent: 1        
}

Это облегчит работу с дочерними документами (если в вашей бизнес-операции нет родителя). Недостатком является то, что запросы для получения дерева будут медленнее, так как данные должны быть «объединены», однако MongoDB дает вам возможность получить родительский элемент с его дочерними элементами, выполнив $ graphLookup :

 {
     $graphLookup: {
        from: "sameCollection",
        startWith: "$parent",
        connectFromField: "parent",
        connectToField: "child",
        as: "tree"
     }
 }

$graphLookup работает рекурсивно, вы можете указать maxDepth.

Можно также рассмотреть гибридный подход - хранить дерево отдельно для быстрого чтения и сохранять данные реляционными для операций дочернего уровня. Задача в этом случае состоит в том, как обрабатывать обновления данных, поскольку одно и то же значение дублируется в нескольких документах. Вы можете рассмотреть возможные модели согласованности, такие как пересоздание вашего дерева каждый час на основе текущих данных, или просто запустить повторную обработку дерева при восстановлении дочернего объекта - это действительно зависит от ваших бизнес-требований.

...