Undo Unwind 在 mongodb 中聚合

Moh*_*ain 1 mongodb node.js 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
}
Run Code Online (Sandbox Code Playgroud)

我正在做分组companyId并且它的工作很好但是我想matchData 根据matchtimematchId为此目的进行搜索,我$unwind matchData在放松之后我使用这样的搜索查询

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

它给了我正确的结果,但是在应用 unwind 之后有什么方法可以撤消它我使用 unwind 只是在子文档中搜索,或者有任何其他方法可以在子文档中搜索。

Nei*_*unn 8

好吧,您当然可以只使用$push$first在 a$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" }
    }}
])
Run Code Online (Sandbox Code Playgroud)

但是您可能应该$filter首先使用MongoDB 3.2:

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") ] }
                   ]
                }
            }
        }
    }}
])
Run Code Online (Sandbox Code Playgroud)

如果你至少有 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]
            ]
        }
    }}
])
Run Code Online (Sandbox Code Playgroud)

当每个数组元素都有一个“唯一”标识符时,这完全没问题,因此“设置”操作只是false$map.

这两种方法都可以在不实际使用的情况下从数组中“过滤”内容 $unwind


注意:不确定您是否真的掌握了$in它用于匹配“条件列表”而不是要求匹配数组。所以一般情况下,条件可以是:

 "matchData.matchId": ObjectId("57175c25561d87001e666d12")
Run Code Online (Sandbox Code Playgroud)

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