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, я думаю, это то, что вы ищете.
Вам придется запускать несколько запросов, но вам обязательно нужно это сделать на стороне приложения.