MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Използване на оператор $slice за получаване на последния елемент от масива

Както вече знаете, $slice се използва само в проекция за ограничаване на елементите на масива, върнати в резултатите. Така че ще останете да обработвате списъка програмно с резултати от find().

По-добър подход е да се използва агрегат. Но първо нека разгледаме как $slice се използва:

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

Така че получавате последния елемент от масива, но сте заседнали в цикъла на резултатите, тъй като не можете да съпоставите стойността на последния елемент. Може и просто да сте направили това в код.

Сега нека разгледаме агрегат :

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

Дори ако това е първото ви използване на aggregate(), препоръчвам ви да научите . Това е може би най-полезният ви инструмент за решаване на проблеми. Определено беше за мен. Поставете всяка стъпка веднъж в даден момент, ако учите.

Също така не сте сигурни във формуляра на вашия документ, всички 1: { ... } нотацията на поддокумента изглежда е грешка, но трябва да изчистите това или да коригирате кода по-горе, за да се позовава на "1.relevancy" вместо. Надявам се, че документите ви наистина изглеждат по-така:

{ "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 и по-нова версия

Разбира се, MongoDB 3.2 въвежда оператор за "агрегиране" за $slice и още по-добър $arrayElemAt оператор, който премахва необходимостта от $unwind и $group обработка. След първоначалния $match заявка просто правите "логическо съвпадение" с $redact :

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

Това ще направи проверката на последния елемент от масива, когато реши дали да $$KEEP или $$PRUNE документите от върнатите резултати.

Ако все още искате "проекцията", тогава всъщност можете да добавите $slice :

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

Или алтернативният подход на:

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

Но вероятно е по-евтино да направите $redact първо и "след това" направете преоформяне в `$project.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да свържете локална база данни Mongo към docker

  2. MongoDB - Експортиране на данни

  3. Автоматично архивиране на MongoDB

  4. Индексиране на поле, което е в масив от поддокументи

  5. премахнете _id от резултата от mongo