【问题标题】:How to find consecutive documents with count in MongoDB?如何在 MongoDB 中查找具有计数的连续文档?
【发布时间】:2019-10-30 17:28:13
【问题描述】:

我收集了从用户那里收到的消息。我想按按时间戳排序的用户名的连续序列对其进行分组。 我有如下所述的收集消息:

{
    "_id":ObjectId("AAAA")
    "userName":"Krunal"
    "message":"Krunal types some text",
    "timestamp":ISODate("2019-06-17T11:57:00.000")
}
{
    "_id":ObjectId("AAAB")
    "userName":"Krunal"
    "message":"Krunal types some text again",
    "timestamp":ISODate("2019-06-17T11:59:00.000")
}
{
    "_id":ObjectId("AAAC")
    "userName":"Krunal"
    "message":"Krunal types some text one more time",
    "timestamp":ISODate("2019-06-17T12:05:00.000")
}
{
    "_id":ObjectId("AAAD")
    "userName":"Karan"
    "message":"Karan type some text",
    "timestamp":ISODate("2019-06-17T12:07:00.000")
}
{
    "_id":ObjectId("AAAE")
    "userName":"Karan"
    "message":"Karan type some more text",
    "timestamp":ISODate("2019-06-17T12:10:00.000")
}
{
    "_id":ObjectId("AAAC")
    "userName":"Krunal"
    "message":"Krunal types some text one more time",
    "timestamp":ISODate("2019-06-17T12:12:00.000")
}

我使用 4 字节的对象 id 使其易于阅读,在实际场景中它将是 mongodb 生成的实际对象 id 从上面的集合中,我想要如下所述的输出:

{
    "userName":"Krunal",
    "count":3,
    "timestamp":ISODate("2019-06-17T12:05:00.000")
}
{
    "userName":"Karan",
    "count":2,
    "timestamp":ISODate("2019-06-17T12:10:00.000")
}
{
    "userName":"Krunal",
    "count":1,
    "timestamp":ISODate("2019-06-17T12:12:00.000")
}

我想统计来自用户名的用户的连续消息 mongodb中是否有可用的查询,或者我需要在简单的查找查询后编写单独的算法?

编辑: 我不想只按用户名分组。我想要的是按用户名与连续文档分组。例如,考虑上面提到的集合。 Krunal 已连续发送 3 条消息,因此 Krunal:3,然后 Karan 已连续发送 2 条消息,因此 Karan:2,现在 Krunal 又发送了一条消息,但在 karan 之后,它将成为新对象,如 Krunal:1,不会增加之前的 Krunal 计数

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    使用这个。

    db.collection.aggregate([{"$group": {"_id":"$userName","count": {$sum:1},"timestamp": {"$first": "$$ROOT.timestamp"}}}])
    

    【讨论】:

    • 感谢您的回答,但这会给我每个用户名的消息计数。我希望与分离连续的文件相同。我已经在我的 quetition 中包含了预期的输出
    【解决方案2】:
    db.collection.aggregate(
    
        // Pipeline
        [
            // Stage 1
            {
                $group: {
                    _id: '$userName',
                    count: {
                        $sum: 1
                    },
                    timestamp: {
                        $last: '$timestamp'
                    }
    
                }
            },
    
            // Stage 2
            {
                $project: {
                    userName: '$_id',
                    count: 1,
                    timestamp: 1,
                    _id: 0
                }
            },
    
        ]
    
    
    
    );
    

    【讨论】:

      【解决方案3】:

      这是我想出的解决方案。

      这不是一个单一的聚合查询,而是我使用 mongo 脚本(可以用 mongo 执行的 Javascript 文件)中的 forEach 循环遍历每个条目。

      var prev_name = "";
      var count = 0;
      var obj_dict = {};
      var entries = [];
      var prev_timestamp;
      
      db.wikidata.find().forEach(function(entry) {
          var name = entry["userName"];
          if(prev_name === ""){
              count += 1;
              prev_name = name;
              prev_timestamp = entry["timestamp"];
          } else if(prev_name === name){
              count += 1;
              prev_timestamp = entry["timestamp"];
          } else {
              obj_dict["userName"] = prev_name;
              obj_dict["count"] = count;
              obj_dict["timestamp"] = prev_timestamp;
              entries.push(obj_dict);
              prev_name = name;
              count = 1;
              prev_timestamp = entry["timestamp"];
              obj_dict = {};
          }
      })
      
      obj_dict["userName"] = prev_name;
      obj_dict["count"] = count;
      obj_dict["timestamp"] = prev_timestamp;
      entries.push(obj_dict);
      
      print(JSON.stringify(entries));
      

      输出:

      [{"userName":"Krunal","count":3,"timestamp":"2019-06-17T12:05:00.000Z"},{"userName":"Karan","count":2,"timestamp":"2019-06-17T12:10:00.000Z"},{"userName":"Krunal","count":1,"timestamp":"2019-06-17T12:12:00.000Z"}]
      

      希望对你有帮助。

      【讨论】:

      • 感谢@Shubham Vaishnav 的回答。是的,它可以使用后处理来完成,但我正在寻找它是否只能使用 mongodb 查询来完成
      猜你喜欢
      • 2022-01-01
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 2015-01-29
      • 2016-03-21
      相关资源
      最近更新 更多