如果您正在谈论从 GUID 中提取时间戳并将其减少为离散的一天,那么 MongoDB 将不会对您有太大帮助。您将需要一个外部语言实现来支持这样的功能并实现一个外部 mapReduce 进程,例如使用 Hadoop。
这让我想知道我们实际上是在谈论 GUID,还是您实际上是指 ObjectID,这将是您文档的 _id 字段的默认值,除非它已被特别覆盖以具有GUID 在那里。
即使不是这样,您也可以通过在文档中添加某种“时间戳”字段并使用正确的 BSON Date 对象类型来帮助您,如下所示:
{
_id:guid,
"timestamp": ISODate("2014-05-27T00:00:00Z")
"clientId":guid,
"reference":'abc123'
"items":
[
{ _id:guid, category:'A', length:100, active:true },
{ _id:guid, category:'B', length:150, active:true },
{ _id:guid, category:'A', length:10, active:false },
{ _id:guid, category:'A', length:111, active:true },
]
}
这允许您使用 MongoDB 聚合框架,因为它可以对这种类型的 Date 对象进行操作,以便将结果分解为离散的日期:
db.collection.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": {
"day": { "$dayOfYear": "$timestamp" },
"category": "$items.category"
},
"countOfItems": { "$sum": 1 },
"countOfActive": {
"$sum": {
"$cond": [
"$items.active",
1,
0
]
}
},
"sumOfLength": { "$sum": "$items.length" }
}}
])
这不仅以 MongoDB 可以做到的最快方式为您提供结果,而且“时间戳”值对于过滤日期范围内的查询也很有用,这是您无法从其他值轻松做到的事情。
在 MongoDB mapReduce 可用的 JavaScript 中还有一种方法可以让您从 ObejctId 获取日期。不过,这比聚合框架运行得慢:
db.collection.mapReduce(
function() {
var date = this._id.getTimestamp();
items.forEach(function(item) {
var day =
"" + date.getFullyear() +
"" + ( date.getMonth() + 1 ) +
"" + date.getDate();
emit(
{
day: day,
category: item.category
},
{
countOfItems: 1,
countOfActive: ( item.active ) ? 1 : 0,
sumOfLength: item.length
}
);
});
},
function( key, values ) {
var reduced = {
countOfItems: 0,
countOfActive: 0,
sumOfLength: 0
};
values.forEach(function(value) {
for ( var k in value ) {
reduced[k] += value[k];
}
});
return reduced;
},
{
"out": { "inline": 1 }
}
)
这基本上做同样的事情,映射器分解数组并提供分组键,而reducer只是总结来自映射器的值。因此,即使您必须从 GUID 中提取,在使用 Hadoop 时为您提供使用 Java 等语言的映射器和化简器的基本布局。
查看aggregate 和mapReduce 手册页,了解有关您可以应用的选项的更多信息。