Ich weiß, dass diese Frage alt ist, aber ich habe sie bei Google gefunden, nachdem ich eine ähnliche neue Frage beantwortet hatte . Also dachte ich, dass dies die gleiche Behandlung verdient.
Sie können den Leistungseinbruch von $where vermeiden durch Verwendung von aggregate stattdessen:
db.example.aggregate([
// Use an index, which $where cannot to narrow down
{$match: { "comments.by": "Abe" }},
// De-normalize the Array
{$unwind: "$comments"},
// The order of the array is maintained, so just look for the $last by _id
{$group: { _id: "$_id", comments: {$last: "$comment"} }},
// Match only where that $last comment by `by.Abe`
{$match: { "comments.by": "Abe" }},
// Retain the original _id order
{$sort: { _id: 1 }}
])
Und das sollte um $wo herumlaufen da wir in der Lage waren, die Dokumente einzugrenzen, die hatten ein Kommentar von "Abe" an erster Stelle. Wie gewarnt, $wo wird jedes Dokument in der Sammlung testen und niemals einen Index verwenden, selbst wenn einer verwendet werden soll.
Natürlich können Sie das Originaldokument auch mit der hier beschriebenen Technik
pflegen auch, also würde alles genau wie ein find()
funktionieren .
Nur ein Denkanstoß für alle, die das finden.
Update für moderne MongoDB-Releases
Moderne Versionen haben den $redact
hinzugefügt
Pipeline-Ausdruck sowie $arrayElemAt
( letzteres ab 3.2, also wäre das hier die minimale Version ), was in Kombination einem logischen Ausdruck erlauben würde, das letzte Element eines Arrays zu untersuchen, ohne ein $unwind
Stufe:
db.example.aggregate([
{ "$match": { "comments.by": "Abe" }},
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Die Logik hier erfolgt im Vergleich, wobei $arrayElemAt
erhält den letzten Index des Arrays -1
, das nur in ein Array der Werte in "by"
umgewandelt wird Eigenschaft über $map
. Dies ermöglicht den Vergleich des einzelnen Werts mit dem erforderlichen Parameter "Abe"
.
Oder sogar etwas moderner mit $expr
für MongoDB 3.6 und höher:
db.example.find({
"comments.by": "Abe",
"$expr": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
}
})
Dies wäre bei weitem die leistungsfähigste Lösung zum Abgleichen des letzten Elements innerhalb eines Arrays, und es wird erwartet, dass es die Verwendung von $where
in den meisten Fällen und besonders hier.