2013-11-21 1 views
2

У меня есть 3 коллекции в MongoDB, которые не могут изменить их схему. Некоторым запросам необходимо получить доступ к 3 коллекциям.Каков наиболее эффективный способ запроса нескольких коллекций в MongoDB?

Я знаю, что мне нужно несколько запросов для этого, но я не уверен, что самый эффективный способ сделать это. Пример упрощенного примера:

Мои данные содержат коллекцию «Пользователь», которая служит логическим родителем для двух других коллекций. Две другие коллекции - «DVD» и «CD». Пользователь может иметь несколько компакт-дисков или DVD-дисков

User Document 
id : "jim", 
location : "sweden" 

CD Document 
name : "White Album", 
owner : "jim" 

DVD Document 
name : "Fargo", 
owner : "jim" 

Теперь подход, который я принимаю сейчас, заключается в следующем. Если я хочу вернуть все компакт-диски и DVD-диски для пользователей в Швеции.

Шаг 1

Get all users in Sweden and return a cursor 

Шаг 2

Iterate through the each user in the cursor and perform a lookup on both the DVD and CD collections to see if the users id matches the owner field 

Шаг 3

If it does add the user to an array to be returned 

Этот подход требует 2а и мне кажется неэффективным. Есть ли более эффективный способ сделать это?

+0

Почему CD и DVD не находятся в одной коллекции? – Philipp

+0

@Phillip Это просто упрощенный пример – Travis

ответ

2

Вы можете сделать некоторые улучшения на запрос следующим образом.

  • При выборе пользователей верните только поле id.

db.user.find ({место: "швеция"}, {идентификатор: 1})

  • Создать список строк, содержащие имена пользователей и передавать этот список с помощью $ в query.Run $ в запросе на CD & коллекции двд следующим образом:
db.cd.find({owner : {$in : ["jim", "tom", ...]}}) 
db.dvd.find({owner : {$in : ["jim", "tom", ...]}}) 

Также добавьте индексы в коллекциях, чтобы улучшить выполнение запросов.

+0

Я уже пробовал этот подход, но был обеспокоен тем, что коллекция пользователей может содержать очень большое количество пользователей. SO, используемый массив может содержать 1 миллион + пользователей. Будет ли массив этого размера зависеть от запроса? – Travis

+0

AFAIK, нет предела в размере массива, переданном оператору $ in. Единственным ограничением здесь является размер документа Bson (16 мб). Если у вас размер массива 1M, вы можете запустить такой же запрос 10 раз, передав 100K в запрос $. Это все же лучше, чем запуск запроса 1M. –

+0

Проекция Hmm не сделает запрос более эффективным, он только уменьшит количество данных при возврате. Также, что вы подразумеваете под строковым списком имен пользователей? Как это работает? – Sammaye

0

Это не так неэффективно, как кажется.

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

MongoDB передает потоки непосредственно из файлов данных каждый пакет курсора, что означает, что его данные «живут» из базы данных, в отличие от набора результатов. Это также означает, что pinging нечетный запрос также много ресурсов ресурса.

Один из вариантов, как вы сказали, возвращает всех пользователей и каждого итерационного судьи, если они должны отображаться, поскольку у них есть связанные записи. Это может равномерно распределять курсоры, останавливающие перегрузку, однако по-прежнему существует вероятность перегрузки курсора на сервере.

Еще один вариант - перебрать всех пользователей из Швеции и вернуть огромный массив user_id, с помощью которого можно запросить сбор компакт-дисков и DVD-дисков. Оттуда вы затем сопоставляете их в своем приложении и возвращаете по мере необходимости.

Однако, как именно вы решаете это, ваш сценарий и сколько данных у вас есть.

0

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

  • users_ids * = Получить все users_id из коллекций DVD и CD. Получите всех пользователей, которые имеют id в * users_ids *, и из Швеции.

Тогда у вас всего 2 запроса, но если ваши коллекции DVD и CD достаточно велики, это, вероятно, не будет быстрее, чем ваш метод, даже если этот метод использует только 2 запроса.

Имейте в виду, что меньшее количество запросов не обязательно обязательно быстрее.

Извините за английский;)