Схема документа MongoDB - PullRequest
       7

Схема документа MongoDB

2 голосов
/ 25 ноября 2011

Я работал над веб-проектом со слоем базы данных MongoDB.У меня есть определенная сущность, которую я не могу сопоставить с документом db должным образом, подумал, что было бы лучше получить некоторую обратную связь.

Скажем, у меня есть коллекции User и Item.Пользователи могут любить или не любить предметы.В элементах также есть теги, и пользователям также могут нравиться или не нравиться теги.Мне нужно быть в состоянии достаточно быстро отыскивать счетчики симпатий / нелюбов.

Я придумал что-то вроде этого (для предмета):

{
    name: "Item Name",
    statistics : {
        likes:      5,
        dislikes:   6
    },
    tags: [
        { name: "Foo", likes: 10, dislikes: 20 },
        { name: "Bar", likes: 5,  dislikes: 1  }
    ]
}

Это довольно прилично.Но проблема в том, что мне нужно знать, понравился ли пользователь / не понравился тег или элемент.Теперь я пришел к следующему:

{
    name: "Item Name",
    statistics : {
        likes:      5,
        dislikes:   6
    },
    tags: [
        { 
            name: "Foo", 
            likes: 2, 
            dislikes: 1,
            votes: [
                { user: "user1_id", vote: 1 }, //like 
                { user: "user2_id", vote: 1 }, //like 
                { user: "user3_id", vote: -1 }, //dislike 
            ]
        },
        { 
            name: "Bar", 
            likes: 0,  
            dislikes: 0,
            votes: []
        }
    ]
}

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

Но я ожидаю около 10 тегов в каждом элементе, возможно, по 100 голосов в каждом.Тогда у меня есть около 1000 вложенных объектов голосования для каждого элемента.Я знаю, что mongodb может обрабатывать документы размером 16 Мб, но все же, можно ли хранить столько данных в одном документе?

Стоит ли переходить на нормализованную модель.Может быть, с коллекцией "tagvotes" и коллекцией itemvotes?На самом деле это кажется мне более естественным.

Просто блуждаю, думаю ли я об отношениях или рационально?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 25 ноября 2011

В какой-то момент попытка внедрить все становится невозможным в любой ситуации типа M x N по мере роста M и N. Задолго до того, как вы достигнете этой точки, вам нужно создать отдельную коллекцию и выполнить соединения на стороне клиента; но это не значит, что вы должны полностью все нормализовать.

В этом случае подумайте о том, какие представления вы хотите показать пользователю: ясно, что вы захотите показать элемент, сколько ему нравится и не нравится, а также набор тегов, которые были применены к нему, и, возможно, насколько популярны каждый из них. из этих тегов есть. Но фактический список пользователей, которым понравился / не понравился объект, а также понравился / не понравился каждый тег, можно перейти в отдельный документ (в отдельную коллекцию).

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

1 голос
/ 25 ноября 2011

нормально ли хранить столько данных в одном документе?

Я не вижу проблем с количеством данных, которые вы сохраняете для каждого объекта, ноВаши шаблоны чтения / обновления вызывают беспокойство: каждый раз, когда вы выбираете элемент, вы также получаете все голоса, идентификатор каждого пользователя и т. д. Кроме того, при добавлении голосов вы увеличиваете объект.Иногда MongoDB придется перераспределять ваш объект, что занимает немного времени.Со временем он узнает, что вы часто выращиваете объекты, и коэффициент заполнения будет увеличиваться, но часто растущие объекты - не лучшая идея.

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

Это немного сложно.Вы можете использовать $pull и $push, но я не знаю, как вы можете синхронизировать счетчики likes и dislikes.Кроме того, что произойдет, если пользователь действительно передумал?Вам нужно было бы сделать и $push, и $pull, и это невозможно, если я правильно запомнил.

Просто интересно, думаю ли я об отношениях или рационально?

Оба.Это проблема отношений: -)

Теперь я хотел бы заключить, что вы должны денормализовать счет и сохранить отношения в другой коллекции, но Hightechrider уже написал это.Слишком медленно.;-)

...