Эффективно определяйте владельца записи в иерархии с помощью MongoDB

Я пытаюсь добиться следующего:

Выберите все записи, которыми я владею, где право собственности - это объекты, которые я создал, ИЛИ объекты, созданные пользователем, которым я управляю, где управление пользователями может быть в иерархии пользователей, управляющих пользователями

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

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

Я подумал, что, возможно, нужно было выполнить некоторую математику, чтобы сделать это - иметь идентификаторы, которые можно каким-то образом хешировать, чтобы определить, принадлежат ли они кому-либо в цепочке команд.

Есть ссылки на подобные вещи?

Я упускаю что-то очевидное?

Используя MongoDB, если это имеет значение, но я рад подумать о других базах данных для вдохновения.

ОБНОВЛЕНИЕ: создали коллекцию MongoDB с 1 000 000 записей, чтобы получить надежные данные о том, что именно составляет управляемое количество параметров для предложения IN в запросе. Сообщу, когда у меня будет конкретная информация.

АНАЛИЗ:

Использование ruby-mongo-driver и библиотеки тестов ruby.

Коллекция MongoDB с 1039944 записями

Записи определяются как:

{
    first_name: String,
    last_name: String,
    email: String,
    phone: String,
    company: String,
    owner: BSON::ObjectId
 }

Со случайно сгенерированными значениями для всех полей.

Поле Владелец имеет индекс.

Выполнение запросов со следующими условиями:

conditions = {"owner" => { "$in" => id_list }}
opts = {skip: rand, limit: 100}

Полученные результаты:

    # 10201 ids
    #              user     system      total        real
    # 0:       0.240000   0.000000   0.240000 (  0.265148)
    # 1:       0.240000   0.010000   0.250000 (  0.265757)
    # 2:       0.240000   0.000000   0.240000 (  0.267149)
    # 3:       0.240000   0.000000   0.240000 (  0.269981)
    # 4:       0.240000   0.000000   0.240000 (  0.270436)
    # Find:    0.240000   0.000000   0.240000 (  0.266709)


    # 5201 ids
    #              user     system      total        real
    # 0:       0.120000   0.000000   0.120000 (  0.133824)
    # 1:       0.120000   0.000000   0.120000 (  0.134787)
    # 2:       0.110000   0.000000   0.110000 (  0.133262)
    # 3:       0.110000   0.000000   0.110000 (  0.136046)
    # 4:       0.120000   0.000000   0.120000 (  0.141220)
    # Find:    0.130000   0.000000   0.130000 (  0.139110)

    # 201 ids
    #              user     system      total        real
    # 0:       0.010000   0.000000   0.010000 (  0.006044)
    # 1:       0.000000   0.000000   0.000000 (  0.004681)
    # 2:       0.010000   0.000000   0.010000 (  0.004578)
    # 3:       0.000000   0.000000   0.000000 (  0.007048)
    # 4:       0.010000   0.000000   0.010000 (  0.008487)
    # Find:    0.000000   0.000000   0.000000 (  0.005990)

    # 1 id (NOT using IN)
    #              user     system      total        real
    # 0:       0.000000   0.000000   0.000000 (  0.002868)
    # 1:       0.000000   0.000000   0.000000 (  0.004937)
    # 2:       0.010000   0.000000   0.010000 (  0.003151)
    # 3:       0.000000   0.000000   0.000000 (  0.002983)
    # 4:       0.000000   0.000000   0.000000 (  0.003313)
    # Find:    0.000000   0.000000   0.000000 (  0.002742)

Даже со списком из 10 тыс. Идентификаторов в запросе производительность довольно высокая.


person Toby Hede    schedule 21.11.2011    source источник
comment
Поразмыслив, я полагаю, что если бы существовала волшебная функция для вычисления родителей, то тяжелая работа с вложенными наборами, материализованными путями и списками смежности для получения деревьев в БД была бы спорной.   -  person Toby Hede    schedule 21.11.2011


Ответы (1)


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

Если список идентификаторов пользователей все еще управляем, вы можете выполнить запрос типа where ownerId in (?,?,?,?,?...) (после первого определения списка):

db.documents.find({owner:{$in: [1234, 2345, 4444, 77777, 99999]}})

Способ NoSQL, вероятно, заключается в денормализации вещей, например, путем включения в документ не только ownerId, но и полного пути вверх по иерархии управления:

{  _id: 'the document A',
   owner : 1234,
   managers: [ 2345, 4444, 77777, 99999 ]
}

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

person Thilo    schedule 21.11.2011
comment
Затем проиндексируйте managers и используйте для поиска элементы Multikeys. - person mu is too short; 21.11.2011
comment
Да, вариант IN - это то, на что я смотрел. Проблема в том, что у менеджеров банок есть менеджеры, и каждый раз, когда изменяется разрешение, вам нужно просматривать всю коллекцию, сбрасывая все. Ясно, что это не идеальный способ решения проблемы. - person Toby Hede; 21.11.2011
comment
С опцией IN изменения разрешений будут в порядке, потому что вам не нужно обновлять саму коллекцию (просто запросите с разными идентификаторами). Если вы сделаете денормализацию, то да, вам придется перестроить индекс. Избежание этого было основным преимуществом нормализации и объединений, но вы не получите этого без СУБД. - person Thilo; 21.11.2011
comment
Ах, я понимаю, что вы имеете в виду ... найдите все идентификаторы пользователя, сопоставьте их. Денормализированный подход сломается почти мгновенно. - person Toby Hede; 21.11.2011
comment
Но в любом случае я не думаю, что могу полагаться на управляемость списка идентификаторов. - person Toby Hede; 21.11.2011