2010-09-15 12 views
6

Verbindungen haben ein oder mehrere Tags, also auf den ersten könnte es natürlich erscheinen die Tags einzubetten:Wie würden Sie diese Abfragen effizient in MongoDB implementieren?

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']} 

Wie würden diese Abfragen ausgeführt werden effizient?

  • Get Links, die einen oder mehrere gegebene Tags enthalten (für Verbindungen mit bestimmten Tags suchen)
  • Hier finden Sie eine Liste aller Tags ohne Wiederholung (für Suchfeld Autovervollständigung)
  • Holen Sie sich die beliebtesten Tags (nach oben 10 Tags anzeigen oder eine Tag-Wolke)

die Idee, die Verbindung, wie oben darstellen basiert auf der MongoNY presentation schieben 38.

Antwort

4

Verbindungen erhalten, die „Wert“ Tag enthalten :

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

Get Links, die "val1", "val2" Tags enthalten:

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

Get Liste aller Tags ohne Wiederholung:

db.col.distinct("tags"); 

die beliebtesten Tags Get - diese ist nicht etwas, das auf einer vorhandenen db abgefragt werden kann, was Sie tun müssen, ist ein Popularitätsfeld hinzuzufügen, das immer aktualisiert wird, wenn eine Abfrage das Dokument abruft, und dann eine Abfrage mit dem Sortierfeld, das auf die Popularität eingestellt ist.

Update: vorgeschlagene Lösung für die Popularitätsfunktion. Versuchen Sie, die folgende Auflistung hinzuzufügen, nennen wir sie Tags.

doc = {tag: String, pop: Integer}

nun einmal Sie eine Abfrage, die Sie alle Tags sammeln, die gezeigt wurden (diese aggregiert und asynchron ausgeführt werden kann), so lassen Sie uns sagen, dass Sie mit dem Ende folgende Tags: "tag1", "tag2", "tag3".

Anschließend rufen Sie die Update-Methode und erhöhen den Pop-Feldwert:

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

Um eine Popularität Feld für einen Tag hinzuzufügen, der Tag müßte in eine separate Sammlung hinzugefügt oder verschoben werden, richtig? – randomguy

+0

müssen Sie nicht, Sie könnten es in der gleichen Sammlung behalten und einfach ein dbref verwenden, um auf das Tag zu zeigen. Eine andere Sammlung wird es einfacher machen, Ihre Daten zu verwalten (was ich empfehle). – Asaf

+0

In der Tagsammlung würde ich vorschlagen, den Tag-Namen in das _id-Feld zu setzen, anstatt ein separates Tag-Feld zu verwenden. Auch wenn es Ihnen nichts ausmacht, ein Update pro Tag durchzuführen, anstatt $ in zu verwenden, können Sie die Abfrage nur {_id: "tag_name"} erstellen und die Funktion upsert verwenden, um neue Tag-Einträge zu erstellen. – mstearn

0

Sie können auch Ihren Tag-Array zu ändern $ addToSet verwenden, um statt $ Push. Dies ändert das Dokument nicht, wenn das Tag bereits existiert. Dies wird ein wenig effizienter sein, wenn Sie Ihre Tags häufig ändern (da die Dokumente nicht so stark wachsen). Hier ist ein Beispiel:

> 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" ] } 
Verwandte Themen