Запрос MongoDB для нескольких полей массива объектов - PullRequest
0 голосов
/ 30 октября 2019

Я новичок в MongoDB, и у меня действительно сложное требование, по которому я пытаюсь написать запрос. Можно ли как-нибудь написать запрос mongodb для этого требования?

Пример строки Mongodb:

Row1 --> {
    array1:[
            { type=“abc”, action=“taken”, points=10},
            { type=“abc”, action=“given”, points=20},
            { type=“xyz”, action=“given”, points=40},
            { type=“xyz”, action=“taken”, points=30}
        ]
     // other fields
}
Row2 --> {
    array1:[
            { type=“xyz”, action=“given”, points=50},
            { type=“xyz”, action=“taken”, points=40}
        ]
     // other fields
}
Row3 --> {
    array1:[
            { type=“abc”, action=“taken”, points=100},
            { type=“abc”, action=“given”, points=200},
            { type=“xyz”, action=“given”, points=500},
            { type=“xyz”, action=“taken”, points=400}
        ]
     // other fields
}

Требование:

Условия фильтра:

Возвращать строки только в том случае, если разница type="abc" и (указывает, когда action="given" - указывает, когдаaction="taken")> 0

Сортировка:

Строки должны быть отсортированы в порядке убывания разницы между (точки, когда action="given" и type="xyz") и(указывает, когда action="taken" и type="xyz")

Ожидаемый результат::

Row3 --> {
    array1:[
            { type=“abc”, action=“taken”, points=100},
            { type=“abc”, action=“given”, points=200},
            { type=“xyz”, action=“given”, points=500},
            { type=“xyz”, action=“taken”, points=400}
        ]
     // other fields
}
Row1 --> {
    array1:[
            { type=“abc”, action=“taken”, points=10},
            { type=“abc”, action=“given”, points=20},
            { type=“xyz”, action=“given”, points=40},
            { type=“xyz”, action=“taken”, points=30}
        ]
     // other fields
}

Объяснение выхода:: Строка 2 не будет поступать в выходные данные, поскольку условие фильтра не выполняется (в массиве нет элементов с type="abc")

Строка 3 идет перед строкой 1 в ответе из-за условия сортировки (это значение разницы больше в строке 3, чем в строке 1 -> (точки, когда action="given" и type="xyz") и (точки, когда action="taken" и type="xyz"))

1 Ответ

0 голосов
/ 31 октября 2019

Попробуйте это:
(Рабочий пример по адресу: https://mongoplayground.net/p/-rSHiqBwlEJ) [Просто нажмите кнопку «Выполнить»]

db.collection.aggregate([
{
    // 01) Filtering out documents that have type "abc"...
    $match: {"array1.type" : "abc" },
},
{
    // 02) Transforming every element of the array in one document...
    $unwind: "$array1",
},
{
    // 03) Summing the values by type ...
    $group: {
        _id: '$_id',
        totalAbc: {
            $sum: { 
                $cond: { 
                    if: {$and:[{$eq: [ "$array1.action", "given"]},{$eq: [ "$array1.type", "abc"]}]},
                    then: "$array1.points",
                    else: {
                        if: {$and:[{$eq: [ "$array1.action", "taken"]},{$eq: [ "$array1.type", "abc"]}]},
                        then: {$multiply: ["$array1.points", -1]},
                        else: 0
                    } 
                } 
             }
        },
        totalXyz: {
            $sum: { 
                $cond: { 
                    if: {$and:[{$eq: [ "$array1.action", "given"]},{$eq: [ "$array1.type", "xyz"]}]},
                    then: "$array1.points",
                    else: {
                        if: {$and:[{$eq: [ "$array1.action", "taken"]},{$eq: [ "$array1.type", "xyz"]}]},
                        then: {$multiply: ["$array1.points", -1]},
                        else: 0
                    } 
                } 
             }
        },
    }
},
{
    // 04) Filtering the result where the total of type "abc" is greater than 0...
   $match: {"totalAbc": {$gt: 0} }
},
{
    // 05) Sorting the result by the total of type "xyz" ...
    $sort: { totalXyz : -1 }
}, 
{ 
    // 06) With id I retrieve all the original document information...
    $lookup: {
       from: "collection",
       localField: "_id",
       foreignField: "_id",
       as: "temp"
    }
},
{
    // 07) Designing the information in the same structure as the original documents ...
    $project: {"_id": "$temp._id", "array1": "$temp.array1"}
}
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...