2015-10-05 5 views
5

Ich habe eine Mongo Sammlung von Nachrichten, die wie folgt aussieht:Mongo Art auf eine berechnete Bedingung

{ 
    'recipients': [], 
    'unRead': [], 
    'content': 'Text' 
} 

Empfänger ist ein Array von Benutzer-IDs und ungelesen ist ein Array aller Benutzer, die noch nicht die geöffnet Botschaft. Das funktioniert wie beabsichtigt, aber ich brauche die Liste aller Nachrichten abzufragen, so dass sie die ersten 20 Ergebnisse zurückgibt, Priorisierung der ungelesenen diejenigen zuerst, so etwas wie:

db.messages.find({recipients: {$elemMatch: userID} }) 
    .sort({unRead: {$elemMatch: userID}}) 
    .limit(20) 

Aber das funktioniert nicht. Wie lassen sich die Ergebnisse am besten priorisieren, je nachdem, ob sie bestimmten Kriterien entsprechen?

Antwort

5

Wenn Sie möchten, „Gewicht“ Ergebnisse nach bestimmten Kriterien haben oder irgendeine Art von „errechneten Wert“ innerhalb einer „Art“, dann müssen Sie die .aggregate() Methode statt. Dies ermöglicht „projiziert“ Wert in dem $sort Betrieb verwendet werden, für die nur eine gegenwärtige Feld in dem Dokument verwendet werden kann:

db.messages.aggregate([ 
    { "$match": { "messages": userId } }, 
    { "$project": { 
     "recipients": 1, 
     "unread": 1, 
     "content": 1, 
     "readYet": { 
      "$setIsSubset": [ [userId], "$unread" ] } 
     } 
    }}, 
    { "$sort": { "readYet": -1 } }, 
    { "$limit": 20 } 
]) 

Hier wird der $setIsSubset Operator ermöglicht einen Vergleich des „ungelesen“ Array mit einer konvertierten Array von [userId], um zu sehen, ob es Übereinstimmungen gibt. Das Ergebnis ist entweder true wo die userId existiert oder false wo nicht.

Dies kann dann zu $sort weitergegeben werden, was die Ergebnisse mit Vorliebe auf die Spiele bestellt (SORT true auf decending) und schließlich $limit gibt nur die Ergebnisse bis zur Höhe angegeben.

Also, um einen berechneten Begriff für "Sortieren" zu verwenden, muss der Wert in das Dokument "projiziert" werden, damit es sortiert werden kann. Der Aggregationsrahmen ist, wie Sie dies tun.

Beachten Sie auch, dass $elemMatch nicht erforderlich ist, nur um einen einzelnen Wert innerhalb eines Arrays zu vergleichen, und Sie müssen nur den Wert direkt angeben. Sein Zweck ist, wo "mehrere" Bedingungen auf einem einzelnen Array-Element erfüllt werden müssen, was natürlich hier nicht gilt.

+0

Das hat perfekt funktioniert. Vielen Dank! Der einzige Kommentar, den ich machen werde, ist, dass Mongo einen Fehler geworfen hat, bis ich $ setIsSubSet zu $ ​​setIsSubset änderte. – beatniknight

+0

@beatniknight Typisch für mich. Der Dokumentationslink war richtig, aber mein camelCase-Gehirn sagt immer, es seien zwei Wörter und tippt es so ein. –

Verwandte Themen