sql >> Database teknologi >  >> NoSQL >> MongoDB

Sådan sorteres efter 'værdi' af en specifik nøgle i en ejendom, der er gemt som et array med k-v-par i mongodb

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() .




  1. Opdater mange dokumenter i mongoDB med forskellige værdier

  2. mongodb replicaset new member viser ikke den korrekte diskbrug på EC2

  3. Synkroniser mongo-databaser på forskellige servere

  4. Brug MongoEngine og PyMongo sammen