Wie Sie inzwischen wissen, wird $slice nur in der Projektion verwendet, um die in den Ergebnissen zurückgegebenen Array-Elemente zu begrenzen. Sie würden also mit der programmgesteuerten Verarbeitung der Liste mit Ergebnissen von find() feststecken.
Ein besserer Ansatz ist die Verwendung von Aggregaten. Aber zuerst betrachten wir, wie $slice wird verwendet:
> db.collection.find({},{ relevancy: {$slice: -1} })
{ "_id" : ObjectId("530824b95f44eac1068b45c0"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c2"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c3"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c4"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c6"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c7"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c8"), "relevancy" : [ "N" ] }
Sie erhalten also das letzte Array-Element, aber Sie müssen die Ergebnisse in einer Schleife durchlaufen, da Sie nicht abgleichen können der letzte Elementwert. Sie hätten dies auch einfach im Code tun können.
Sehen wir uns nun aggregate an :
db.collection.aggregate([
// Match things so we get rid of the documents that will never match, but it will
// still keep some of course since they are arrays, that *may* contain "N"
{ "$match": { "relevancy": "Y" } },
// De-normalizes the array
{ "$unwind": "$relevancy" },
// The order of the array is retained, so just look for the $last by _id
{ "$group": { "_id": "$_id", "relevancy": { "$last": "$relevancy" } }},
// Match only the records with the results you want
{ "$match": { "relevancy": "Y" }},
// Oh, and maintain the original _id order [ funny thing about $last ]
{ "$sort": { "_id": 1 } }
])
Auch wenn dies Ihre erste Verwendung von Aggregat() wäre, empfehle ich Ihnen, es zu lernen . Es ist vielleicht Ihr nützlichstes Werkzeug zur Problemlösung. Sicherlich war es für mich. Geben Sie jeden Schritt einmal ein zu einem Zeitpunkt, wenn Sie lernen.
Auch nicht sicher auf Ihrem Dokumentenformular, alle 1: { ... }
Die Notation von Unterdokumenten scheint ein Fehler zu sein, aber Sie sollten das korrigieren oder den obigen Code anpassen, um auf "1.relevancy"
zu verweisen stattdessen. Ich hoffe, Ihre Dokumente sehen in Wirklichkeit eher so aus:
{ "relevancy" : [ "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c0") }
{ "relevancy" : [ "Y", "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c2") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c3") }
{ "relevancy" : [ "Y", "Y" ], "_id" : ObjectId("530824b95f44eac1068b45c4") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c6") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c7") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c8") }
MongoDB 3.2.x und höher
Natürlich führt MongoDB 3.2 einen "Aggregations"-Operator für $slice
ein und ein noch besseres $arrayElemAt
-Operator, der $unwind
überflüssig macht und $group
wird bearbeitet. Nach dem anfänglichen $match
Abfrage machen Sie einfach eine "logische Übereinstimmung" mit $redact
:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Dadurch wird das letzte Element des Arrays überprüft, wenn entschieden wird, ob $$KEEP
ausgeführt werden soll oder $$PRUNE
die Dokumente aus den zurückgegebenen Ergebnissen.
Wenn Sie immer noch die "Projektion" wollen, können Sie die $slice
tatsächlich hinzufügen :
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } }
])
Oder der alternative Ansatz von:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
{ "$match": { "relevancy": "Y" } }
])
Aber $redact
ist wahrscheinlich weniger kostspielig first und "then" führen alle Umformungen in `$project.