MongoDB - имитировать соединение или подзапрос

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

Скажем, у меня есть классический пример пользователей и сообщений, с пользователями в одной коллекции и сообщениями в другой. Я хочу найти все сообщения пользователей, которые являются "london".

Я упростил ситуацию в этом вопросе, в моем сценарии реального мира хранение сообщений в виде массива в документе пользователя не будет работать, так как у меня есть 1000 "сообщений" для каждого пользователя, постоянно вставляемого.

Может ли помочь Mongos $в операторе? Может ли $обрабатывать массив из 10 000 000 записей?

Ответ 1

Честно говоря, если вы не можете поместить "Посты" в "Пользователи", у вас есть два варианта.

  • Денормализовать некоторые пользовательские данные внутри сообщений. Затем вы можете искать только одну коллекцию.
  • Сделайте два запроса. (один, чтобы найти пользователей, других найти сообщения)

Исходя из вашего вопроса, вы пытаетесь сделать # 2.

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

Может ли $обрабатывать массив из 10 000 000 записей?

Посмотрите, если вы планируете "запрашивать" свои сообщения для всех пользователей в наборе 10 000 000 пользователей, вы уже прошли этап "запроса". Вы говорите себе, что каждый пользователь имеет 1000 сообщений, поэтому вы говорите о запросе "Пользователи с сообщениями, которые живут в Лондоне", возвращая 100Ms записей.

Записи 100M - это не запрос, а набор данных!

Если вы беспокоитесь о нарушении команды $in, я настоятельно рекомендую вам использовать map/reduce. Mongo Map/Reduce создаст новую коллекцию для вас. Затем вы можете обрезать или суммировать этот набор данных по своему усмотрению.

Ответ 2

$in может обрабатывать 100 000 записей. Я никогда не пробовал 10 000 000 записей, но запрос (запрос также является документом) должен быть меньше 4 МБ (как и каждый документ), поэтому невозможно использовать 10,0000,0000 записей.

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

Это означает, что вы должны обновлять сообщения, когда город пользователя изменяется, но это происходит не очень часто. Это обновление будет быстро, если вы проиндексируете UserId в коллекции Posts.

Ответ 3

У меня что-то похожее, но моя настройка ориентирована на "пользователей" и "сообщений". То, что я сделал, это добавить ссылку на пользователя, вроде внешнего ключа. Я использовал сгенерированный "_id" из коллекции пользователей и сохранил его как ключ внутри "сообщений". Для каждого сообщения, которое отправляет пользователь, я сохраняю его в коллекции сообщений. Вы должны прочитать dbrefs, я думаю, это то, что вы ищете.

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