【问题标题】:Undo Unwind in aggregate in mongodb在 mongodb 中撤消 Unwind
【发布时间】:2016-08-15 15:20:26
【问题描述】:

我有多个类似这样的数据

{
    "_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 分组,它的工作正常但我想在matchData 中搜索基于matchtimematchId 为此我是$unwind matchData 在展开后我使用这样的搜索查询

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

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

【问题讨论】:

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


    【解决方案1】:

    您当然可以在$group 中使用$push$first 来使文档恢复原状:

    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”操作只是从$map 中删除false 值。

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


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

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

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

    【讨论】:

      猜你喜欢
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 2018-07-10
      • 2019-05-30
      • 2014-09-27
      • 1970-01-01
      相关资源
      最近更新 更多