sql >> Databasteknik >  >> NoSQL >> MongoDB

Använder operatorn $slice för att få det sista elementet i arrayen

Som du vet vid det här laget, används $slice endast i projektion för att begränsa arrayelementen som returneras i resultaten. Så du skulle ha fastnat med att bearbeta listan programmatiskt med resultat från en find().

Ett bättre tillvägagångssätt är att använda aggregat. Men låt oss först överväga hur $slice används:

> 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 sista arrayelementet, men du har fastnat med att loopa resultaten eftersom du inte kan matcha det sista elementvärdet. Du kan lika gärna ha gjort detta i kod.

Låt oss nu titta på sammanslagna :

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 } }
])

Även om detta skulle vara din första användning av aggregate(), rekommenderar jag att du lär dig det . Det är kanske ditt mest användbara problemlösningsverktyg. Det har det säkert varit för mig. Lägg in varje steg en gång åt gången om du lär dig.

Också osäker på ditt dokumentformulär, alla 1: { ... } notering av underdokument verkar vara ett misstag men du bör rensa upp det eller justera koden ovan för att referera till "1.relevancy" istället. Jag hoppas att dina dokument faktiskt ser mer ut så här:

{ "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 och uppåt

Naturligtvis introducerar MongoDB 3.2 en "aggregation"-operator för $slice och en ännu bättre $arrayElemAt operatör som tar bort behovet av någon $unwind och $group bearbetning. Efter den första $match fråga gör du bara en "logisk matchning" med $redact :

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

Det kommer att göra inspektionen på det sista elementet i arrayen när man beslutar om $$KEEP ska eller $$PRUNE dokumenten från de returnerade resultaten.

Om du fortfarande ville ha "projektionen" kan du faktiskt lägga till $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 det alternativa tillvägagångssättet:

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

Men det är förmodligen mindre kostsamt att göra $redact först och "sedan" gör någon omformning i `$project.



  1. Networkx slutar aldrig beräkna Betweenness centrality för 2 mil noder

  2. MongoDB map()

  3. MongoDB - Importera data

  4. Uppdatera kapslade underdokument i MongoDB med arrayFilters