如何在MongoDB中执行复杂查询

如何在MongoDB中执行复杂查询,mongodb,aggregation-framework,mongodb-aggregation,Mongodb,Aggregation Framework,Mongodb Aggregation,我想在此架构上执行查询: { "name" : "xxx", "guests" : [ { "category" : "category 1", "arrived" : false }, { "category" : "category 2", "arrived" : false }, { "

我想在此架构上执行查询:

{ 
   "name" : "xxx",
   "guests" : [ 
       {
            "category" : "category 1",
            "arrived" : false
       },
       {
            "category" : "category 2",
            "arrived" : false
       },
       {
            "category" : "category 1",
            "arrived" : true
       },
       {
            "category" : "category 2",
            "arrived" : true
       }
   ]
}
我想得到一个特定的名字,每个类别的客人到达的百分比列表

对于上面作为示例的文档,我希望收到:

{
    name : "xxx",
    results : [
         {
              category : "category 1",
              arrived : 50 (percent)
         },
         {
              category : "category 2",
              arrived : 50 (percent)
         },
    ]

有没有一种方法可以通过单个MongoDB查询实现这一点?另外,我应该在客户端还是服务器端执行此计算?

您可以使用聚合。下面是一个例子:

[
    {
        $match: {name:"xxx"}
    },
    {
        $unwind: "$guests"
    },
    {
        $group: {
            _id:"$guests.category",
            guests_arrived: {
                $sum: { $cond: [ {$eq:["$guests.arrived",true]}, 1, 0 ] }
            },
            guests_total: {
                $sum: 1
            }
        }
    },
    {
        $project:{
            _id: false,
            category: "$_id",
            guests_arrived:true,
            guests_total:true,
            "percent": {
                $multiply: [
                    100,
                    {$divide: ["$guests_arrived","$guests_total"]}
                ]

            }
        }
    }
]
对使用的聚合管道阶段的说明:

$匹配名称,因为您只需要特定名称的结果

$展开来宾数组,以便在下一阶段对其成员执行聚合函数

$group by category,以$合计客人总数和已到达的客人数量 $cond/$eq用于评估到达时间,如果到达时间=真,则仅添加到客人到达时间


$project,主要目的是根据前一阶段的合计值、来宾到达和来宾总数计算百分比

您可以使用AGGRATE。下面是一个例子:

[
    {
        $match: {name:"xxx"}
    },
    {
        $unwind: "$guests"
    },
    {
        $group: {
            _id:"$guests.category",
            guests_arrived: {
                $sum: { $cond: [ {$eq:["$guests.arrived",true]}, 1, 0 ] }
            },
            guests_total: {
                $sum: 1
            }
        }
    },
    {
        $project:{
            _id: false,
            category: "$_id",
            guests_arrived:true,
            guests_total:true,
            "percent": {
                $multiply: [
                    100,
                    {$divide: ["$guests_arrived","$guests_total"]}
                ]

            }
        }
    }
]
对使用的聚合管道阶段的说明:

$匹配名称,因为您只需要特定名称的结果

$展开来宾数组,以便在下一阶段对其成员执行聚合函数

$group by category,以$合计客人总数和已到达的客人数量 $cond/$eq用于评估到达时间,如果到达时间=真,则仅添加到客人到达时间


$project,主要目的是根据前一阶段的合计值、来宾到达和来宾总数计算百分比,几乎不进行任何处理的哑数据存储。它只是存储和检索数据。您应该尊重这一目标,并尽量避免强迫MongoDB执行任何可以在客户端上完成的计算,除非您愿意承担沉重的性能惩罚。即使是琐碎的任务,如查找平均值或求和字段,通常也应该推送到客户端。解决应该在哪里进行计算的问题,一般来说,复杂的计算应该在客户端完成,因为MongoDB应该是一个大而哑的数据存储,几乎不进行任何处理。它只是存储和检索数据。您应该尊重这一目标,并尽量避免强迫MongoDB执行任何可以在客户端上完成的计算,除非您愿意承担沉重的性能惩罚。即使是一些琐碎的任务,比如求平均值或求和字段,通常也应该推送到客户机上。谢谢,它确实起作用了!你能解释一下你做了什么使它工作吗?谢谢,它确实工作了!你能解释一下你是怎么做到的吗?