首先,你需要平均里程數,單日平均里程在給定的時間段,或平均里程超過經理的生活?我會考慮添加時間戳字段。是的,_id有時間戳,但這隻反映文檔創建的時間,不一定是第一天的日誌時間。
注意事項的第一個數據模型:
- 是否每個文件代表某一天,或者一個經理?
- 你期望在陣列中有多少「貨車」?這個列表隨着時間的推移而增長嗎您是否需要在一兩年內考慮最大16MB的文檔大小?
考慮第二個數據模型:
- 你可以存儲管理器的名稱爲「經理標識」領域?這可以用作次元查找的唯一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
} }
]);
我在平均計算過程中添加了一組名稱(車輛?)。
相關文章:
嗨,謝謝你的建議。我確實嘗試過,它的工作,但avg_mile返回是0.000? – deejuk
有錯誤,更新了答案,再試一次:) – bagrat
等待忘記刪除.miles中的$。這很有用,所以可以多謝你的幫助。幾英里呢? x 7,然後在列表中顯示,而不是平均值 – deejuk