Структура данных MongoDB с большим количеством внутренних документов

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

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

Поскольку я уверен, что вам всем наскучило слушать, я привык к земле RDB, где я выложил бы свою схему как

| USER |
--------
|ID
|Name
|Etc.

|TWEET__|
---------
|ID
|UserID
|Etc

Кажется, что логическая схема в Mongo будет

User
|-Tweet (0..3000)
  |-Entities
    |-Hashtags (0..10+)
    |-urls (0..5)
    |-user_mentions (0..12)
  |-GeoData (0..20)
|-somegroupID

но не будет ли это быстро раздувать пользовательский документ сверх емкости. Но я хотел бы провести анализ твитов, принадлежащих пользователям с похожим somegroupID. Концептуально имеет смысл компоновка модели, как указано выше, но в какой момент это слишком громоздко? И каковы жизнеспособные альтернативы?


person Lloyd    schedule 17.02.2012    source источник


Ответы (2)


Вы правы в том, что вы, вероятно, столкнетесь с ограничением размера документа MongoDB в 16 МБ. Вы не говорите, какой анализ вы хотели бы провести, поэтому сложно рекомендовать схему. Схемы MongoDB разработаны с учетом шаблонов запроса данных (и вставки).

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

Я имею в виду дизайн для документа твита как:

{
    'hashtags': [ '#foo', '#bar' ],
    'urls': [ "http://url1.example.com", 'http://url2.example.com' ],
    'user_mentions' : [ 'queen_uk' ],
    'geodata': { ... },
    'userid': 'derickr',
    'somegroupid' : 40
}

А затем для пользовательской коллекции документы могут выглядеть так:

{
    'userid' : 'derickr',
    'realname' : Derick Rethans',
    ...
}
person Derick    schedule 17.02.2012
comment
Я упоминал, что хотел бы провести анализ твитов, принадлежащих пользователям с похожим идентификатором somegroupID. Не нарушит ли шаблон вставки добавление элемента somegroupID в каждый твит, который нужно отслеживать в этой группе? Если я сделаю это таким образом, то выполнение этого mapReduce/анализа этого подмножества станет очевидным. - person Lloyd; 18.02.2012
comment
Я не понимаю, что вы подразумеваете под шаблоном вставки, и вы не упомянули, какой анализ вы хотели бы провести. В любом случае вы, вероятно, захотите избежать M/R, если сможете, и выполнять анализ с помощью обычных запросов. - person Derick; 22.02.2012
comment
Я имел в виду лучшие практики обновления данных. Если пользователь добавляется к somegroupID другого пользователя, мне нужно будет вставить этот somegroupID во все документы твитов, связанные с этим пользователем. Похоже на высокие накладные расходы для вставки. Затем, что касается выполнения анализа с обычными запросами, делает ли Mongo такие вещи, как count() в GROUP BY? Чтобы получить количество твитов в день или что-то в этом роде? - person Lloyd; 22.02.2012

Все заслуги замечательных людей на MongoHQ.com. На мой вопрос ответили на https://groups.google.com/d/msg/mongodb-user/OtEOD5Kt4sI/qQg68aJH4VIJ

Крис Уинслетт @ MongoHQ


Вам будет интересно это видео:

http://www.10gen.com/presentations/mongosv-2011/schema-design-at-scale

По сути, в одном документе хранится один день твитов для одного человека. Рассуждение:

  • Запрос обычно состоит из дней и пользователей

Таким образом, вы можете иметь следующий индекс:

{user_id: 1, date: 1} # Дата должна быть последней, потому что вы будете ранжировать и сортировать по дате

Веселиться!

Крис МонгоHQ


Я думаю, что имеет смысл реализовать следующее:

пользователь

{ user_id: 123123,
  screen_name: 'cledwyn',
  misc_bits: {...},
  groups: [123123_group_tall_people, 123123_group_techies, ],
  groups_in: [123123_group_tall_people]
}

твит

{ tweet_id: 98798798798987987987987,
  user_id: 123123,
  tweet_date: 20120220,
  text: 'MongoDB is pretty sweet',
  misc_bits: {...},
  groups_in: [123123_group_tall_people]
}
person Lloyd    schedule 23.02.2012