2010-09-15 2 views
6

ссылки имеют один или несколько тегов, поэтому сначала может показаться естественным вставлять теги:Как бы вы эффективно реализовали эти запросы в MongoDB?

link = { title: 'How would you implement these queries efficiently in MongoDB?' 
     url: 'http://stackoverflow.com/questions/3720972' 
     tags: ['ruby', 'mongodb', 'database-schema', 'database-design', 'nosql']} 

Как бы эти запросы будут осуществляться эффективно?

  • Получить ссылки, которые содержат один или более данные метки (для поиска ссылок с заданными тегами)
  • Получить список всех тегов без повторений (для поиска ящика автозаполнение)
  • Получить самые популярные теги (для отображения первых 10 тегов или облака тегов)

идеи представлять ссылку, как описано выше основан на MongoNY presentation, слайд 38.

ответ

4

Получить ссылки, которые содержат «значение» тег :

db.col.find({tags: "value"}); 

получить ссылки, которые содержат "val1", "val2" теги:

db.col.find({tags: { $all : [ "val1", "val2" ] }}); 

Получить список всех тегов без повторения:

db.col.distinct("tags"); 

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

Обновление: предлагаемое решение для функции популярности. Попробуйте добавить следующую коллекцию, назовем ее тегами.

док = {тег: String, поп: Integer}

сейчас раз вы запрос собрать все теги, которые были показаны (они могут быть объединены и сделано асинхронно), так скажем, вы в конечном итоге с следующие теги: «tag1», «tag2», «tag3».

Вы затем вызвать метод обновления и увеличения значения поля поп:

db.tags.update({tag: { $in: ["tag1", "tag2", "tag3"] }}, { $inc: { pop: 1 }}); 
+0

Для того, чтобы добавить поле популярности для тега, тег должен был бы быть добавлены или перемещены в отдельную коллекцию, правильно? – randomguy

+0

вам не обязательно, вы можете сохранить его в одной коллекции и просто использовать dbref для указания на тег. другая коллекция упростит вам управление вашими данными (это то, что я рекомендую). – Asaf

+0

В коллекции тегов я бы предложил поместить имя тега в поле _id вместо использования отдельного поля тега. Кроме того, если вы не возражаете делать одно обновление для каждого тега, а не использовать $ in, вы можете сделать запрос просто {_id: "tag_name"} и использовать функцию upsert для создания новых записей тегов. – mstearn

0

Вы также можете использовать $ addToSet изменить тег массива вместо $ нажим. Это не изменяет документ, когда тег уже существует. Это будет немного более эффективно, если вы часто меняете свои теги (поскольку документы не будут расти так сильно). Вот пример:

> db.tst_tags.remove() 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag3'}}, true) 
> db.tst_tags.find() 
{ "_id" : ObjectId("4ce244548736000000003c6f"), "name" : "test", 
    "tags" : [ "tag1", "tag2", "tag3" ] } 
Смежные вопросы