在MongoDB中有一些问题可以找到最好的方法,可以说它是一个关系数据集,所以我可能会被提到。仍然是一个挑战,看它是否可能。
我目前需要由物流经理订购。他们所在部门的货车每日平均里程数,以及每周平均值的单独列表。
数据库中的First先生设置如下
{
"_id" : ObjectId("555cf04fa3ed8cc2347b23d7"),
"name" : "My Manager 1",
"vans" : [
{
"name" : "van1",
"miles" : NumberLong(56)
},
{
"name" : "van2",
"miles" : NumberLong(34)
}
]
}
但我不知道如何通过嵌套数组值排序而不知道父数组键(这些将是标准的0-x)
所以我的下一个选择是废弃这个想法,只是在第一个集合中有名字,第二个集合中的面包车是经理的Id。
所以从上面的例子中移除面包车并添加这个集合(面包车)
{
"_id" : ObjectId("555cf04fa3ed8cc2347b23d9"),
"name" : "van1",
"miles" : NumberLong(56),
"manager_id" : "555cf04fa3ed8cc2347b23d7"
}
但是因为我需要通过经理显示结果,如何在查询中(如果可能)订购此集合中的平均里程,其中id = x,然后按其ID显示经理。
感谢您的帮助
答案 0 :(得分:2)
如果Manager
的{{1}}数量有限,那么您的第一种方法会更好,因为您不必对数据库进行两次单独的调用/查询来收集您的信息
接下来是如何计算每Van
平均值的问题,其中Aggregation Framework
将对您有所帮助。这是一个可以获得所需数据的查询:
Manager
第一个db.manager.aggregate([
{$unwind: "$vans"},
{$group:
{_id:
{
_id: "$_id",
name: "$name"
},
avg_milage: {$avg: "$vans.miles"}
}
},
{$sort: {"avg_milage": -1}},
{$project:
{_id: "$_id._id",
name: "$_id.name",
avg_milage: "$avg_milage"
}
}
])
步骤只需展开$unwind
数组,并为数组的每个元素创建单独的文档。
然后vans
阶段获取具有相同$group
对的所有文档,并在(_id, name)
字段中,计算这些文档中avg_milage
字段的平均值。
miles
阶段显而易见,它只是按降序对文档进行排序,使用新的$sort
字段作为排序键。
最后,最后avg_milage
步骤只是通过做出适当的预测来清理文档,仅用于美容:)
您的第二个期望结果需要类似的事情:
$project
这将生成db.manager.aggregate([
{$unwind: "$vans"},
{$group:
{_id:
{
_id: "$_id",
name: "$name"
},
total_milage: {$sum: "$vans.miles"}
}
},
{$sort: {"total_milage": -1}},
{$project:
{_id: "$_id._id",
name: "$_id.name",
weekly_milage: {
$multiply: [
"$total_milage",
7
]
}
}
}
])
的列表及其每周的milage,按降序排序。因此,您可以Managers
结果,并获得具有最高级别的$limit
。
以非常相似的方式,你可以获取你的货车的信息:
Manager
答案 1 :(得分:1)
首先,您需要一天的平均里程,特定时间段内的平均里程数,或经理人生命周期内的平均里程数吗?我会考虑添加一个时间戳字段。是的,_id有时间戳,但这只反映了文档创建的时间,不一定是初始日志的时间。
第一个数据模型的注意事项:
第二个数据模型的注意事项:
作为@n9code has pointed out,聚合框架就是两种情况下的答案。
对于第一个数据模型,假设每个文档代表一天,并且您想要检索给定日期或天数范围内的平均值:
db.collection.aggregate([
{ $match: {
name: 'My Manager 1',
timestamp: { $gte: ISODate(...), $lt: ISODate(...) }
} },
{ $unwind: '$vans' },
{ $group: {
_id: {
_id: '$_id',
name: '$name',
timestamp: '$timestamp'
},
avg_mileage: {
$avg: '$miles'
}
} },
{ $sort: {
avg_mileage: -1
} },
{ $project: {
_id: '$_id._id',
name: '$_id.name',
timestamp: '$_id.timestamp',
avg_mileage: 1
} }
]);
如果对于第一个数据模型,每个文档代表一个管理器并且“vans”数组每天都在增长,那么这个特定的数据模型并不理想,原因有两个:
为了完整起见,这是查询:
/*
Assuming data model is:
{
_id: ...,
name: ...,
vans: [
{ name: ..., miles: ..., timestamp: ... }
]
}
*/
db.collection.aggregate([
{ $match: {
name: 'My Manager 1'
} },
{ $unwind: '$vans' },
{ $match: {
'vans.timestamp': { $gte: ISODate(...), $lt: ISODate(...) }
} },
{ $group: {
_id: {
_id: '$_id',
name: '$name'
},
avg_mileage: {
$avg: '$miles'
}
} },
{ $sort: {
avg_mileage: -1
} },
{ $project: {
_id: '$_id._id',
name: '$_id.name',
avg_mileage: 1
} }
]);
对于第二个数据模型,聚合更直接。我假设包含一个时间戳:
db.collection.aggregate([
{ $match: {
manager_id: ObjectId('555cf04fa3ed8cc2347b23d7')
timestamp: { $gte: ISODate(...), $lt: ISODate(...) }
} },
{ $group: {
_id: '$manager_id'
},
avg_mileage: {
$avg: '$miles'
}
names: {
$addToSet: '$name'
}
} },
{ $sort: {
avg_mileage: -1
} },
{ $project: {
manager_id: '$_id',
avg_mileage: 1
names: 1
} }
]);
我在平均计算过程中添加了一系列名称(车辆?)。
相关文件: