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

Bruger $slice-operatoren for at få det sidste element i arrayet

Som du ved nu, bruges $slice kun i projektion for at begrænse de array-elementer, der returneres i resultaterne. Så du ville sidde fast med at behandle listen programmatisk med resultater fra en find().

En bedre tilgang er at bruge aggregat. Men lad os først overveje, hvordan $slice bruges:

> db.collection.find({},{ relevancy: {$slice: -1} })
{ "_id" : ObjectId("530824b95f44eac1068b45c0"), "relevancy" : [  "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c2"), "relevancy" : [  "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c3"), "relevancy" : [  "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c4"), "relevancy" : [  "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c6"), "relevancy" : [  "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c7"), "relevancy" : [  "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c8"), "relevancy" : [  "N" ] }

Så du får det sidste array-element, men du sidder fast med at sløjfe resultaterne, da du ikke kan matche den sidste elementværdi. Du kunne lige så godt bare have gjort dette i kode.

Lad os nu se på samlet :

db.collection.aggregate([
    // Match things so we get rid of the documents that will never match, but it will
    // still keep some of course since they are arrays, that *may* contain "N"
    { "$match": { "relevancy": "Y" } },

    // De-normalizes the array
    { "$unwind": "$relevancy" },

    // The order of the array is retained, so just look for the $last by _id
    { "$group": { "_id": "$_id", "relevancy": { "$last": "$relevancy" } }},

    // Match only the records with the results you want
    { "$match": { "relevancy": "Y" }},

    // Oh, and maintain the original _id order [ funny thing about $last ]
    { "$sort": { "_id": 1 } }
])

Selvom dette ville være din første brug af aggregate(), opfordrer jeg dig til at lære det . Det er måske dit mest nyttige problemløsningsværktøj. Det har det bestemt været for mig. Indsæt hvert trin én gang ad gangen, hvis du lærer.

Er heller ikke sikker på din dokumentformular, alle 1: { ... } underdokumentnotation ser ud til at være en fejl, men du bør rydde op eller justere koden ovenfor for at referere til "1.relevancy" i stedet. Jeg håber dog, at dine dokumenter faktisk ser mere sådan ud:

{ "relevancy" : [  "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c0") }
{ "relevancy" : [  "Y",  "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c2") }
{ "relevancy" : [  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c3") }
{ "relevancy" : [  "Y",  "Y" ], "_id" : ObjectId("530824b95f44eac1068b45c4") }
{ "relevancy" : [  "Y",  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c6") }
{ "relevancy" : [  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c7") }
{ "relevancy" : [  "Y",  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c8") }

MongoDB 3.2.x og nyere

Selvfølgelig introducerer MongoDB 3.2 en "aggregation"-operator for $slice og en endnu bedre $arrayElemAt operatør, der fjerner behovet for enhver $unwind og $group forarbejdning. Efter den indledende $match forespørgsel laver du bare et "logisk match" med $redact :

db.collection.aggregate([
    { "$match": { "relevancy": "Y" } },
    { "$redact": {
        "$cond": {
            "if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}   
])

Det vil foretage inspektionen af ​​det sidste element i arrayet, når det besluttes om $$KEEP skal eller $$PRUNE dokumenterne fra de returnerede resultater.

Hvis du stadig ville have "projektionen", kan du faktisk tilføje $slice :

db.collection.aggregate([
    { "$match": { "relevancy": "Y" } },
    { "$redact": {
        "$cond": {
            "if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }},
    { "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } }
])

Eller den alternative tilgang til:

db.collection.aggregate([
    { "$match": { "relevancy": "Y" } },
    { "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
    { "$match": { "relevancy": "Y" } }
])

Men det er sandsynligvis mindre omkostningsfuldt at lave $redact først og "derefter" udfører enhver omformning i `$project.



  1. Spring Data RedisTemplate:Serialisering af værdien og HashValue

  2. mongo - rubin forbindelsesproblem

  3. Hvordan bruger man en variabel som et feltnavn i mongodb-native findOne()?

  4. 5 måder at få måneden fra en dato i MongoDB