Hvis vi antager, at det, du vil have, er alle de dokumenter, der har "point"-værdien som en "nøgle" i arrayet, og derefter sorterer på "værdien" for den "nøgle", så er dette lidt uden for rækkevidden for .find()
metode.
Grunden er, hvis du gjorde noget som dette
db.collection.find({
"setid": 154421, "data.k": "point" }
).sort({ "data.v" : -1 })
Problemet er, at selvom de matchede elementer gør har den matchende nøgle "punkt", er der ingen måde at fortælle hvilken data.v
du henviser til for den slags. Også en sort
i .find()
resultater vil ikke gøre noget som dette:
db.collection.find({
"setid": 154421, "data.k": "point" }
).sort({ "data.$.v" : -1 })
Hvilket ville være forsøg at bruge en positionsoperator inden for en sortering, der i det væsentlige fortæller hvilket element der skal bruge værdien af v
på. Men dette er ikke understøttet og vil sandsynligvis ikke være det, og for den mest sandsynlige forklaring vil denne "indeks"-værdi sandsynligvis være forskellig i hvert dokument.
Men denne form for selektiv sortering kan udføres ved hjælp af .aggregate()
.
db.collection.aggregate([
// Actually shouldn't need the setid
{ "$match": { "data": {"$elemMatch": { "k": "points" } } } },
// Saving the original document before you filter
{ "$project": {
"doc": {
"_id": "$_id",
"setid": "$setid",
"date": "$date",
"version": "$version",
"data": "$data"
},
"data": "$data"
}}
// Unwind the array
{ "$unwind": "$data" },
// Match the "points" entries, so filtering to only these
{ "$match": { "data.k": "points" } },
// Sort on the value, presuming you want the highest
{ "$sort": { "data.v": -1 } },
// Restore the document
{ "$project": {
"setid": "$doc.setid",
"date": "$doc.date",
"version": "$doc.version",
"data": "$doc.data"
}}
])
Det forudsætter selvfølgelig data
array har kun en element, der har nøglepunkterne. Hvis der var mere end én, skal du $group
før den slags som denne:
// Group to remove the duplicates and get highest
{ "$group": {
"_id": "$doc",
"value": { "$max": "$data.v" }
}},
// Sort on the value
{ "$sort": { "value": -1 } },
// Restore the document
{ "$project": {
"_id": "$_id._id",
"setid": "$_id.setid",
"date": "$_id.date",
"version": "$_id.version",
"data": "$_id.data"
}}
Så der er én brug af .aggregate()
for at gøre noget komplekst sortering på dokumenter og stadig returnere det originale dokumentresultat i sin helhed.
Læs mere om aggregationsoperatører
og de generelle rammer. Det er et nyttigt værktøj at lære, som tager dig længere end .find()
.