Wiem, że to pytanie jest stare, ale znalazłem je w Google po udzieleniu odpowiedzi na podobne nowe pytanie . Więc pomyślałem, że zasługuje to na takie samo traktowanie.
Możesz uniknąć spadku wydajności $where za pomocą agregacji zamiast tego:
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 }}
])
I to powinno krążyć wokół $gdzie ponieważ udało nam się zawęzić dokumenty, które miały komentarz "Abe" w pierwszej kolejności. Zgodnie z ostrzeżeniem, $gdzie przetestuje każdy dokument w kolekcji i nigdy nie użyje indeksu, nawet jeśli taki istnieje.
Oczywiście możesz również zachować oryginalny dokument, korzystając z techniki opisanej tutaj
również, więc wszystko działałoby jak find()
.
Tylko do myślenia dla każdego, kto to znajdzie.
Aktualizacja dla nowoczesnych wydań MongoDB
Nowoczesne wersje dodały $redact
wyrażenie potoku, a także $arrayElemAt
(ta ostatnia od 3.2, więc byłaby to minimalna wersja tutaj), która w połączeniu pozwoliłaby wyrażeniu logicznemu na sprawdzenie ostatniego elementu tablicy bez przetwarzania $unwind
etap:
db.example.aggregate([
{ "$match": { "comments.by": "Abe" }},
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Logika jest tutaj wykonana w porównaniu z $arrayElemAt
pobiera ostatni indeks tablicy -1
, który jest przekształcany w tablicę wartości w "by"
właściwość za pośrednictwem $map
. Pozwala to na porównanie pojedynczej wartości z wymaganym parametrem "Abe"
.
Lub nawet nieco bardziej nowoczesny przy użyciu $expr
dla MongoDB 3.6 i nowszych:
db.example.find({
"comments.by": "Abe",
"$expr": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
}
})
Byłoby to zdecydowanie najbardziej wydajne rozwiązanie do dopasowywania ostatniego elementu w tablicy i faktycznie powinno zastąpić użycie $where
w większości przypadków, a zwłaszcza tutaj.