【问题标题】:Perform $group and count in mongoDB aggregation在 mongoDB 聚合中执行 $group 和 count
【发布时间】:2022-01-20 15:04:21
【问题描述】:

鉴于我有一个复杂的分组要求,我想知道实现我想要的结果的最佳方法是什么。 我的数据($project 阶段的结果)看起来像这样:

{
_id:$id
status:"available"
inspectionStatus:"done"
state:"completed"
category:"One"
},
{
_id:$id
status:"booked"
inspectionStatus:"none"
state:"active"
category:"Two"
},
.
.
.

我尝试使用$facet 创建多个存储桶,因为我尝试创建的分组是$status + $state + $inspection 的聚合,但是执行时间是不可接受的,占用了@987654326 @ 毫秒。 我不能使用 $accumulator 因为 mongoDB 版本(虽然我们总是可以升级到 4.4.x),但我不确定使用 $accumulator 是否会产生更好的响应时间。

包含$facet 阶段:

{
  "available": [
    {"$match": 
      {$and: [
        {"status": "available"},
        {"inspectionStatus": "done"}
      ]}
    }
  ],
  "matched": [
    {"$match": 
      {$and: [
        {"status": "booked"},
        {"state": "booked"}
        ]
      }
    }
  ],
  "inIntake": [ 
    {"$match": 
      {$and: [
        {"status": "available"},
        {"inspectionStatus": {$ne: "done"}}
        ]
      }
    }
  ],
  "active": [
    {"$match": 
      {$and: [
        {"status": "booked"},
        {"state": "active"}
        ]
      }
    }
  ],
  "unreturned":[
    {"$match": 
      {"status": "forceCompleted"}
    }
  ]
}

【问题讨论】:

  • 你是说你想{$group: {_id: {status:"$status",state:"$state",inspection:"$inspection}, n: {$sum:1} }} 吗?这将计算状态/状态/检查的所有组合。
  • 不是真的...我不需要所有组合,我需要组合的子集unreturnedactiveinIntakeactiveavailable
  • 我怀疑你在这里不需要$facet,因为你没有使用引擎对任何东西进行分组,只是过滤。如果子集在总集合大小中占很大比例,甚至不要使用$match:只需执行`简单的find() 并使用客户端逻辑选择unreturnedactive 等。如果没有,请使用单个 $match 和一个大的 $or 表达式来处理上述方面 - 您仍然必须使用客户端逻辑来分离结果。
  • 另外:我们在这里讨论了多少文档? 1639763842 毫秒几乎是 19
  • 抱歉复制了错误的值。应该说11333mils。对于79188 记录。

标签: mongodb sum aggregation


【解决方案1】:

如果你真的想将逻辑推送到数据库,这里有一个解决方案——但你仍然需要按文档检查XX 字段文档:

db.foo.aggregate([
    {$addFields: {XX: {$switch: {
    branches: [
            { case: {
        $and: [{$eq:["$status","available"]},{$eq:["$inspectionStatus","done"]}]
            }, then:'AVAILABLE' },
            { case: {
        $and: [{$eq:["$status","booked"]},{$eq:["$state","booked"]}]
            }, then:'MATCHED' },
            { case: {
        $and: [{$eq:["$status","available"]},{$ne:["$inspectionStatus","done"]}]
            }, then:'IN_INTAKE' },
            { case: {
        $and: [{$eq:["$status","booked"]},{$eq:["$state","active"]}]
            }, then:'ACTIVE' },
            { case: {
        $eq:["$status","forceCompleted"]
            }, then:'UNRETURNED' },
    ],
        default: null
    }}
                 }}
    ,{$match: {XX: {$ne: null}}}
]);

在这方面的端到端时间实际上比简单的find() 好很多毫秒,因为传输的材料更少,但当然 DB 引擎在处理管道时会更加努力。

【讨论】:

    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2020-08-07
    • 2020-09-22
    • 2017-10-08
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多