【问题标题】:How to pipeline for document如何为文档流水线
【发布时间】:2018-09-06 20:57:11
【问题描述】:

我收集了这样的文档:

{ "_id" : ObjectId("5b91035eca4f00000124e1d8"), "status" : 0, "date" : NumberLong(0), "players" : [ { "name" : "Valentin", "sets" : [ { "points" : [ { "score" : 0, "comment" : "" }, { "score" : 0, "comment" : "" }, { "score" : 0, "comment" : "" }, { "score" : 1, "comment" : "sa" }, { "score" : 1, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 3,"comment" : "sw" }, { "score" : 3, "comment" : "" }, { "score" : 3, "comment" : "" }, { "score" : 4, "comment" : "sa" }, { "score" : 5, "comment" : "bh" }, { "score" : 5, "comment" : "" }, { "score" : 5, "comment" : "" }, { "score" : 6, "comment" : "fh" }, { "score" : 6, "comment" : "" }, { "score" : 7, "comment" : "sw" }, { "score" : 7, "comment" : "" }, { "score" : 7, "comment" : "" }, { "score" : 8, "comment" : "" }, { "score" : 8, "comment" : "" }, { "score" : 9, "comment" : "bh" }, { "score" : 10, "comment" : "sw" }, { "score" : 11, "comment" : "sw" } ] } ] }, { "name" : "Zalupkin", "sets" : [ { "points" : [ { "score" : 0, "comment" : "" }, { "score" : 1, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 2, "comment" : "" }, { "score" : 3, "comment" : "fh"}, { "score" : 4, "comment" : "sw" }, { "score" : 5, "comment" : "" }, { "score" : 6, "comment" : "" }, { "score" : 7, "comment" : "" }, { "score" : 8, "comment" : "sa" }, { "score" : 8, "comment" : "" }, { "score" : 9, "comment" : "fh" }, { "score" : 10, "comment" : "sa" }, { "score" : 11, "comment" : "bh" }, {"score" : 11, "comment" : "" }, { "score" : 12, "comment" : "" }, { "score" : 13, "comment" : "" }, { "score" : 13, "comment" : "" }, { "score" : 13, "comment" : "" }, { "score" : 14, "comment" : "" }, { "score" : 15, "comment" : "sa" }, { "score" : 15, "comment" : "" }, { "score" : 16, "comment" : "sw" }, { "score" : 16, "comment" : "" }, { "score" : 17, "comment" : "" }, { "score" : 18, "comment" : "" }, { "score" : 18, "comment" : "" }, { "score" : 19, "comment" : "sa" }, { "score" : 19, "comment" : "" }, { "score" : 19, "comment" : "" }, { "score" : 19, "comment" : "" } ] } ] } ] }

我尝试制作聚合管道来计算鬃毛评论“sw”有多少玩家名称为“Valentin”。

它也可以在许多文档中,我需要计算整个 cmets。

结果必须是这样的: { "_id" : null, "count" : 0 }

感谢您的帮助。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    也许这行得通:

    db.getCollection('test2').aggregate([
    // Target only the documents which contains player Valentin
    
    { $match: {"players.name" : "Valentin"}},
    
    //Unwind the array players so we can remove the part from the other players
    { $unwind: "$players"},
    
    //Get the players whose name is Valentin of the unwind set
    { $match: {"players.name" : "Valentin"}},
    
    //Reduce the deep of the array so we can count them well
    { $project: {"points": "$players.sets.points"}},
    { $unwind: "$points"},
    { $unwind: "$points"},
    
    //Query of comment match
    { $match: {"points.comment" : "sw" }},
    
    //Calculate count
    { $group: {
        _id: null,
        count: { $sum: 1 }
        }}
    ])
    

    【讨论】:

    • 为什么要用多个{ $unwind: "$points"},有什么秘诀?没有它是行不通的。
    • 是的,它没有。我正在尝试使用地图来编写其他查询。我们要查询的数据在 deep 3 里面。有数组播放器,其中包含数组集合,其中包含数组点。为了能够为某个用户过滤我们想要的cmet,我们需要展开3次才能达到评论所在的级别。无论如何,我相信它可以用更简单的方式完成,让我看看:)
    【解决方案2】:

    您可以尝试以下聚合。

    初始$filter 过滤匹配的玩家和 下一个$filter 过滤comment = 'sw' 的点,然后$size 计算每个点数组中的匹配。使用$map 执行所有集合的逻辑,使用$sum 计算所有集合的所有匹配项

    $group 计算所有文档中的匹配项。

    db.colname.aggregate([
      {"$match":{"players.name":"Valentin"}},
      {"$project":{
        "count":{
          "$sum":{
            "$map":{
              "input":{
                "$let":{
                  "vars":{
                    "mplayer":{
                      "$filter":{"input":"$players","as":"player","cond":{"$eq":["$$player.name","Valentin"]}
                     }
                    }
                  },
                  "in":{"$arrayElemAt":["$$mplayer.sets",0]}
                }
              },
              "as":"set",
              "in":{
                "$size":{
                  "$filter":{"input":"$$set.points","cond":{"$eq":["$$this.comment","sw"]}}
                }
              }
            }
          }
        }
      }},
      {"$group":{"_id":null,"count":{"$sum":"$count"}}}
    ])
    

    【讨论】:

    • 2018-09-06T12:49:51.672+0000 E QUERY [js] 错误:命令失败:{ "ok" : 0, "errmsg" : "Missing 'in' parameter to $let" ,“代码”:16877,“代码名称”:“Location16877”}:聚合失败:_getErrorWithCode@src/mongo/shell/utils.js:25:13 doassert@src/mongo/shell/assert.js:18:14 _assertCommandWorked @src/mongo/shell/assert.js:534:17 assert.commandWorked@src/mongo/shell/assert.js:618:16 DB.prototype._runAggregate@src/mongo/shell/db.js:260:9 DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1056:12 @(shell):1:1 >
    • 抱歉。现在更新了。请再试一次。
    • 是的!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 2017-05-21
    • 2019-01-06
    • 2016-11-10
    • 2014-04-04
    • 2012-09-02
    • 1970-01-01
    相关资源
    最近更新 更多