Om du antar att det du vill ha är alla dokument som har "points"-värdet som en "nyckel" i arrayen och sedan sorterar på "värdet" för den "nyckeln", så är detta lite utanför räckvidden för .find()
metod.
Anledningen är att du gjorde något liknande
db.collection.find({
"setid": 154421, "data.k": "point" }
).sort({ "data.v" : -1 })
Problemet är att även om de matchade elementen gör har den matchande nyckeln "punkt", det finns inget sätt att säga vilken data.v
du syftar på för den sorten. Dessutom en sort
inom .find()
resultat kommer inte att göra något så här:
db.collection.find({
"setid": 154421, "data.k": "point" }
).sort({ "data.$.v" : -1 })
Vilket skulle vara försöker att använda en positionsoperator inom en sortering, som i huvudsak talar om vilket element som ska använda värdet på v
på. Men detta stöds inte och kommer sannolikt inte att vara, och för den mest troliga förklaringen, skulle det "index"-värdet troligen vara olika i varje dokument.
Men den här typen av selektiv sortering kan göras med hjälp av .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 förutsätter naturligtvis data
arrayen har bara en element som har nyckelpunkterna. Om det fanns mer än en, skulle du behöva $group
före sorten så här:
// 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å det finns en användning av .aggregate()
för att göra något komplicerat sortera på dokument och ändå returnera originaldokumentets resultat i sin helhet.
Läs mer om aggregationsoperatorer
och den allmänna ramen. Det är ett användbart verktyg att lära sig som tar dig bortom .find()
.