Vím, že tato otázka je stará, ale našel jsem ji na Googlu po zodpovězení podobné nové otázky . Takže jsem si myslel, že tohle si zaslouží stejné zacházení.
Můžete se vyhnout výpadku výkonu $where pomocí agregát místo toho:
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 }}
])
A to by se mělo pohybovat kolem $where protože jsme byli schopni zúžit dokumenty, které měly komentář od "Abe" na prvním místě. Jak bylo varováno, $where se chystá otestovat každý dokument v kolekci a nikdy nepoužije index, i když tam nějaký je.
Samozřejmě můžete také udržovat původní dokument pomocí techniky popsané zde
také, takže vše bude fungovat stejně jako find()
.
Jen k zamyšlení pro každého, kdo to najde.
Aktualizace pro vydání Modern MongoDB
Moderní verze přidaly $redact
výraz potrubí a také $arrayElemAt
(poslední od 3.2, takže zde by to byla minimální verze), což by v kombinaci umožnilo logickému výrazu prozkoumat poslední prvek pole bez zpracování $unwind
fáze:
db.example.aggregate([
{ "$match": { "comments.by": "Abe" }},
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Logika je zde provedena ve srovnání, kde $arrayElemAt
získává poslední index pole -1
, který je transformován pouze na pole hodnot v "by"
vlastnost přes $map
. To umožňuje porovnání jedné hodnoty s požadovaným parametrem "Abe"
.
Nebo ještě o něco modernější pomocí $expr
pro MongoDB 3.6 a vyšší:
db.example.find({
"comments.by": "Abe",
"$expr": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
}
})
To by bylo zdaleka nejvýkonnější řešení pro párování posledního prvku v poli a ve skutečnosti se očekává, že nahradí použití $where
ve většině případů a zvláště zde.