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

сортиране по стойност на вграден обект в Mongodb

Ако трябва да изчислите нещо подобно по време на изпълнение, с "филтрирано" съдържание от масива, определящо реда на сортиране, тогава най-добре направете нещо с .aggregate() за преоформяне и определяне на стойност за сортиране като тази:

db.collection.aggregate([
    // Pre-filter the array elements
    { "$project": {
        "tags": 1,
        "score": {
            "$setDifference": [
                { "$map": {
                    "input": "$tags",
                    "as": "tag",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.id", "t1" ] },
                            "$$el.score",
                            false
                        ]
                    }
                }},
                [false]
            ]
        }
    }},
    // Unwind to denormalize
    { "$unwind": "$score" },
    // Group back the "max" score
    { "$group": {
        "_id": "$_id",
        "tags": { "$first": "$tags" },
        "score": { "$max": "$score" }
    }},
    // Sort descending by score
    { "$sort": { "score": -1 } }
])

Където първата част от конвейера се използва за „предварително филтриране“ на съдържанието на масива (както и запазване на оригиналното поле) само до тези стойности на „резултат“, където идентификаторът е равен на „t1“. Това става чрез обработка на $map който прилага условие към всеки елемент чрез $cond за да определи дали да върне "резултат" за този елемент или false .

$setDifference извършва сравнение с масив от един елемент [false] което ефективно премахва всички false стойности, върнати от $map . Като „набор“ това също премахва дублиращи се записи, но за целта на сортирането тук това е добро нещо.

С намаления и преформатиран масив до стойности, вие обработвате $unwind готови за следващия етап на работа с ценностите като отделни елементи. $group етап по същество се прилага $max на "резултат", за да върне най-високата стойност, съдържаща се във филтрираните резултати.

Тогава става въпрос само за прилагане на $sort върху определената стойност да наредите документите. Естествено, ако искате това обратното, използвайте $min и вместо това сортирайте във възходящ ред.

Разбира се, добавете $match етап до началото, ако всичко, което наистина искате, са документи, които всъщност съдържат стойности "t1" за id в рамките на етикетите. Но тази част е от най-малко значение за сортирането на филтрирани резултати, които искате да постигнете.

Алтернативата на изчисляването е да направите всичко, докато пишете записи в масива в документите. Някак объркано, но става нещо подобно:

db.collection.update(
    { "_id": docId },
    {
        "$push": { "tags": { "id": "t1", "score": 60 } },
        "$max": { "maxt1score": 60 },
        "$min": { "mint1score": 60 }
    }
)

Тук $max Операторът за актуализиране задава стойността за посоченото поле само ако новата стойност е по-голяма от съществуващата стойност или в противен случай все още не съществува свойство. Обратният случай е верен за $min , където само ако е по-малко от него ще бъде заменено с новата стойност.

Това разбира се би имало ефекта на добавяне на различни допълнителни свойства към документите, но крайният резултат е, че сортирането е значително опростено:

db.collection.find().sort({ "maxt1score": -1 })

И ще работи много по-бързо от изчисляването с тръбопровод за агрегиране.

Така че помислете за принципите на дизайна. Структурираните данни в масиви, където искате филтрирани и сдвоени резултати за сортиране, означават изчисляване по време на изпълнение, за да се определи по коя стойност да се сортира. Добавяне на допълнителни свойства към документа на .update() означава, че можете просто да посочите тези свойства, за да сортирате директно резултатите.



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

  2. Mongodb:Вземете документи, сортирани по динамично класиране

  3. Meteor:Запазете RegExp обект в сесия

  4. Как се генерират ObjectId на MongoDB?

  5. Съхраняване на приятелски отношения в MongoDB?