撤消mongodb中的聚合展开

时间:2016-04-22 06:16:55

标签: node.js mongodb mongodb-query aggregation-framework

我有多个像这样的数据

{
    "_id" : ObjectId("57189fcd72b6e0480ed7a0a9"),
    "venueId" : ObjectId("56ce9ead08daba400d14edc9"),
    "companyId" : ObjectId("56e7d62ecc0b8fc812b2aac5"),
    "cardTypeId" : ObjectId("56cea8acd82cd11004ee67a9"),
    "matchData" : [ 
        {
            "matchId" : ObjectId("57175c25561d87001e666d12"),
            "matchDate" : ISODate("2016-04-08T18:30:00.000Z"),
            "matchTime" : "20:00:00",
            "_id" : ObjectId("57189fcd72b6e0480ed7a0ab"),
            "active" : 3,
            "cancelled" : 0,
            "produced" : 3
        }, 
        {
            "matchId" : ObjectId("57175c25561d87001e666d13"),
            "matchDate" : ISODate("2016-04-09T18:30:00.000Z"),
            "matchTime" : "20:00:00",
            "_id" : ObjectId("57189fcd72b6e0480ed7a0aa"),
            "active" : null,
            "cancelled" : null,
            "produced" : null
        }
    ],
    "__v" : 0
}

我正在按companyId进行分组并且其工作正常但我想基于matchDatamatchtimematchId中进行搜索为此我$unwind matchData放松后我使用我的搜索查询

db.getCollection('matchWiseData').aggregate([
{"$match":{
   "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}
}},
{"$unwind":"$matchData"},
{"$match":{
    "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}}
}])

它给我正确的结果,但在应用展开后有任何方法来撤消它我使用展开只是搜索内部子文档或有任何其他方式搜索内部子文档。

1 个答案:

答案 0 :(得分:3)

当然,您只需在$push中使用$first$group即可将文档恢复原状:

db.getCollection('matchWiseData').aggregate([
    { "$match":{
       "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}
    }},
    { "$unwind":"$matchData"},
    { "$match":{
        "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}
    }},
    { "$group": {
        "_id": "$_id",
        "venueId": { "$first": "$venueId" },
        "companyId": { "$first": "$companyId" },
        "cardTypeId": { "$first": "$cardTypeId" },
        "matchData": { "$push": "$matchData" }
    }}
])

但你可能应该首先使用MongoDB 3.2 $filter

db.getCollection('matchWiseData').aggregate([
    { "$match":{
       "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}
    }},
    { "$project": {
        "venueId": 1,
        "companyId": 1,
        "cardTypeId": 1,
        "matchData": { 
            "$filter": {
                "input": "$matchData",
                "as": "match",
                "cond": {
                   "$or": [
                       { "$eq": [ "$$match.matchId", ObjectId("57175c25561d87001e666d12") ] }
                   ]
                }
            }
        }
    }}
])

如果你至少拥有MongoDB 2.6,你仍然可以使用$map$setDifference代替:

db.getCollection('matchWiseData').aggregate([
    { "$match":{
       "matchData.matchId":{"$in":[ObjectId("57175c25561d87001e666d12")]}
    }},
    { "$project": {
        "venueId": 1,
        "companyId": 1,
        "cardTypeId": 1,
        "matchData": { 
            "$setDifference": [
                { "$map": {
                    "input": "$matchData",
                    "as": "match",
                    "in": {
                        "$cond": [
                           { "$or": [
                              { "$eq": [ "$$match.matchId", ObjectId("57175c25561d87001e666d12") ] }
                           ]},
                            "$$match",
                            false
                        ]
                    }
                }},
                [false]
            ]
        }
    }}
])

当每个数组元素都具有“唯一”标识符时,这是完全正常的,因此“set”操作只会从false中删除$map值。

这两种方法都可以在不实际使用$unwind

的情况下从数组中“过滤”内容

N.B :不确定您是否真的意识到$in用于匹配“条件列表”,而不是要求匹配数组。所以通常条件可以是:

 "matchData.matchId": ObjectId("57175c25561d87001e666d12")

您实际只有一个值可以匹配的地方。当您拥有条件的“列表”时,可以使用$in$or。数组本身对所需的运算符没有任何影响。