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

Как да сортирате по „стойност“ на конкретен ключ в свойство, съхранено като масив с k-v двойки в mongodb

Ако приемем, че това, което искате, са всички документи, които имат стойността "точки" като "ключ" в масива и след това сортирайте по "стойността" за този "ключ", тогава това е малко извън обхвата на .find() метод.

Причината е, ако сте направили нещо подобно

db.collection.find({
    "setid": 154421, "data.k": "point" }
).sort({ "data.v" : -1 })

Проблемът е, че въпреки че съответстващите елементи правят имат съвпадащия ключ на "точка", няма начин да се каже кой data.v имате предвид за сортирането. Освен това, sort в .find() резултатите няма да направят нещо подобно:

db.collection.find({
    "setid": 154421, "data.k": "point" }
).sort({ "data.$.v" : -1 })

Което би било опитващо за използване на позиционен оператор в рамките на сортиране, като по същество казва кой елемент да използва стойността на v На. Но това не се поддържа и е малко вероятно да бъде и за най-вероятното обяснение тази стойност на „индекс“ вероятно ще бъде различна във всеки документ.

Но този вид селективен сортирането може да се извърши с помощта на .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"
    }} 

])

Разбира се, това предполага data масивът съдържа само един елемент, който има ключови точки. Ако имаше повече от един, ще трябва да $group преди сортирането по този начин:

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

Така че има едно използване на .aggregate() за да направя някокомплекса сортиране на документи и въпреки това връщане на оригиналния документ в пълен размер.

Прочетете още малко за операторите за агрегиране и общата рамка. Това е полезен инструмент за учене, който ви отвежда отвъд .find() .




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongoose:findOneAndUpdate не актуализира съществуващо поле

  2. Какво може да причини топология е разрушена грешка при извикване на db.destroyDatabase с node.js mongodb native?

  3. Възможно ли е да въвеждате прехвърлени данни в тръбопровод за агрегиране на MongoDB?

  4. Грешка с дублиран ключ на Mongoose с upsert

  5. NODE.JS:ФАТАЛНА ГРЕШКА - Разпределението на JS е неуспешно - процесът няма памет, докато анализира големи excel файлове