подход к графическому моделированию для управления доступом пользователей к узлам / границам

Существуют ли наборы лучших практик для подхода к моделированию данных в базе данных графов (сейчас я рассматриваю arangodb, но этот вопрос будет применяться к другим платформам)? Вот практический пример, иллюстрирующий мой вопрос:

Предположим, мы создаем централизованный список контактов для пользователей. У каждого пользователя есть контакты, но некоторые контакты могут быть общими для пользователей, например Джон знает Мэри, а Марк знает Мэри. Таким образом, у меня было бы 3 узла (Джон, Мэри и Марк), но Джон должен видеть только его отношения с Мэри, а не отношения Марка с Мэри.

Итак, как следует разработать полный граф, чтобы поддерживать доступ пользователей к своей информации?

Вариант 1. Создайте по одному графику для каждого пользователя. Таким образом, я точно знаю, кто что может видеть (я мог бы, например, поставить перед всеми своими коллекциями префикс идентификатора пользователя). Это было бы просто, но дублировало бы много данных (например, если бы я поместил всю свою семью в базу данных, мой брат тоже сделал бы это, создав дважды одни и те же данные на разных графиках)

Вариант 2: Создайте 1 общий граф с узлами контактов и узлами пользователей. Я бы подключил контакт Джона, Мэри и Марка, но узел «Пользователь», представляющий Джона, был бы связан только с узлами «Контакт», Джон и Мэри. Таким образом, я мог бы получить только те контактные узлы, которые подключены к узлу User, на котором я сосредоточен. Проблема в том, что ребра не могут быть связаны с узлом пользователя (у меня не может быть ребра, идущего от узла к ребру ... можно?). Поэтому мне пришлось бы добавить атрибут user_id ко всем краям, чтобы получить только те, которые относятся к текущему пользователю. Это немного приятнее, поскольку мне не нужно дублировать узлы, но мне все равно придется дублировать края, поскольку они будут специфичными для пользователя.

Вариант 3: Сделайте это SQL, как с таблицей прав, поддерживая список идентификаторов контактов вместе с тем, какой пользователь может видеть, какой узел и какой край (тяжелые соединения)

Варианты 4: ???

Как и во всем, есть много способов найти решение, но мне было интересно, что считается лучшей практикой для баланса чистоты подхода и производительности для вставки / удаления ... зная, что производительность может зависеть от платформы


person Minh    schedule 05.08.2015    source источник


Ответы (1)


я бы предложил вариант 4:

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

Затем вы можете использовать направленные ребра для создания списка контактов для пользователя. Допустим, у вас есть два пользователя, Джон и Мэри, тогда Джон может добавить Мэри в свой список контактов, но Мэри не узнает. Если она хочет добавить Джона, это означает, что вы добавите второй край. Если вы хотите иметь только симметричные контакты (если Джон добавит Мэри в свой список, он должен автоматически появиться в ее списке), вы просто игнорируете это направление в своих запросах.

Если теперь вы хотите получить контакты для Джона, это можно сделать, выбрав «Соседи Джона».

В ArangoDB это можно реализовать с помощью двух коллекций, скажем Contact и Knows, где Knows удерживает края.

Следующий код, вставленный в arangosh, создает вашу ситуацию, описанную выше:

db._create("Contact");
db._createEdgeCollection("Knows");
db.Contact.save({_key: "John", mail: "[email protected]"});
db.Contact.save({_key: "Mary", mail: "[email protected]"});
db.Contact.save({_key: "Marc", mail: "[email protected]"});

db.Knows.save("Contact/John", "Contact/Mary", {});
db.Knows.save("Contact/Marc", "Contact/Mary", {});

Чтобы запросить список контактов для пользователя Джона:

db._query('RETURN NEIGHBORS(Contact, Knows, "John", "outbound")').toArray()

Должен дать Мэри в результате, никакой информации о Марке.

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

db.Knows.save("User/John", "Contact/Mary", {});
db.Knows.save("User/Marc", "Contact/Mary", {});

db._query('RETURN NEIGHBORS(Users, Knows, "John", "outbound")').toArray()

должен дать такой же результат.

Изменить: Что касается вашего вопроса в варианте 2: в ArangoDB на самом деле можно указать ребра на другие ребра, однако функция построения графа теперь будет рассматривать ребра, на которые указывают, как если бы они были узлами. Это означает, что они не следуют своему направлению автоматически. Но вы можете использовать эти результирующие ребра в дальнейших операторах AQL и продолжить поиск с помощью функций AQL.

person mchacki    schedule 06.08.2015