MongoDB查询对象数组的多个字段

时间:2019-10-30 20:22:09

标签: mongodb mongodb-query

我是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"时的点)和(指向{ {1}}和action="taken"))

1 个答案:

答案 0 :(得分:0)

尝试一下:
(位于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"}
}
])