sql >> Databáze >  >> NoSQL >> MongoDB

Použití operátoru $slice k získání posledního prvku pole

Jak již víte, $slice se používá pouze v projekci k omezení prvků pole vrácených ve výsledcích. Takže byste se zasekli u programového zpracování seznamu s výsledky z find().

Lepším přístupem je použití agregátu. Nejprve se však podívejme, jak $slice se používá:

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

Získáte tedy poslední prvek pole, ale zaseknete se u opakování výsledků, protože se nemůžete shodovat hodnotu posledního prvku. Možná jste to právě udělali v kódu.

Nyní se podíváme na agregát :

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

I když by to bylo vaše první použití agregátu(), doporučuji vám, abyste se naučili . Je to možná váš nejužitečnější nástroj pro řešení problémů. Pro mě určitě bylo. Vložte každý krok jednou v době, kdy se učíte.

Také si nejste jisti ve formuláři dokumentu, zda všechny 1: { ... } zápis dílčího dokumentu se zdá být chybný, ale měli byste to vyčistit nebo upravit výše uvedený kód tak, aby odkazoval na "1.relevancy" namísto. Doufám, že vaše dokumenty ve skutečnosti vypadají spíše takto:

{ "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.xa novější

MongoDB 3.2 samozřejmě zavádí operátor „agregace“ pro $slice a ještě lepší $arrayElemAt operátor, který odstraňuje potřebu jakéhokoli $unwind a $group zpracovává se. Po úvodním $match stačí vytvořit "logickou shodu" s $redact :

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

To provede kontrolu na posledním prvku pole při rozhodování, zda $$KEEP nebo $$PRUNE dokumenty z vrácených výsledků.

Pokud byste stále chtěli "projekci", můžete skutečně přidat $slice :

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

Nebo alternativní přístup:

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

Ale je pravděpodobně méně nákladné provést $redact nejprve a "pak" proveďte jakoukoli změnu tvaru v `$project.



  1. Jak zabezpečit ClusterControl Server

  2. ImportError:Žádný modul s názvem redis

  3. Redis vs. Memcached

  4. Redis INCR souběžnost