代码之家  ›  专栏  ›  技术社区  ›  aless80

在聚合阶段获取多个计算结果

  •  1
  • aless80  · 技术社区  · 6 年前

    我正在使用Mongoose和MongoDB实现一个后端,其“用户”文档如下:

    > db.users.find().pretty()
    {
            "_id" : ObjectId("5c46eb642c825626124b1e3c"),
            "username" : "admin",
            "searches" : [
                    ISODate("2019-01-30T14:52:07Z"),
                    ISODate("2019-01-30T14:53:40Z"),
                    ISODate("2019-01-30T14:54:48Z"),
                    ISODate("2019-02-03T17:11:57Z"),
                    ISODate("2019-02-04T06:40:00Z")
            ]
    }
    

    搜索字段是一个数组,记录用户运行某些搜索功能的时间。我想选择一个用户名并计算在过去一小时、一天和总共运行了多少次搜索。我的问题是在一个查询中获取这三个值。

    我正在使用聚合选择用户,使用“展开”提取搜索,按时查询(例如,超过一小时前的日期),并计算结果。

    >let now = new Date()
    ISODate("2019-02-04T06:56:29.095Z")
    >let onehourago = new Date(now.getTime() - 1000 * 3600);
    >let yesterday = new Date(now.getTime() - 1000 * 3600 * 24);
    >let queryUser = { $match: {username: "admin"}};
    >let unwind = { $unwind : "$searches" };
    >let queryTime = { $match: {searches: {$gte: onehourago}}};
    >let counter = {$count: "lasthour"};
    >db.users.aggregate([queryUser, unwind, queryTime, counter])
    { "lasthour" : 1 }
    

    我想得到:

    { "lasthour" : 1, "today": 2, "total": 5 }
    

    如果在没有匹配项的情况下查询返回0而不是空的话(但我可以在javascript中解决这个问题),那么就有一个额外的好处。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Ashh    6 年前

    你可以用 $filter 聚合以筛选出 searches 大堆

    db.collection.aggregate([
      { "$match": { "username": "admin" }},
      { "$project": {
        "total": { "$size": "$searches" },
        "lasthour": {
          "$size": {
            "$filter": {
              "input": "$searches",
              "as": "search",
              "cond": {
                "$and": [
                  { "$gte": ["$$search", onehourago] },
                  { "$lte": ["$$search", now] }
                ]
              }
            }
          }
        },
        "today": {
          "$size": {
            "$filter": {
              "input": "$searches",
              "as": "search",
              "cond": {
                "$and": [
                  { "$gte": ["$$search", yesterday] },
                  { "$lte": ["$$search", now] }
                ]
              }
            }
          }
        }
      }}
    ])