我曾经通过PHP在mongoDB上分组,以获得我项目的最大日期。由于我有太多的项目(超过10 000个(,我读到我必须使用MapReduce。
这是我过去的组函数:
$keys = array('ItemDate'=> true);
$initial = array('myLastDate' => 0);
$reduce = "function(obj, prev) {
if (myLastDate < obj.ItemDate) {
myLastDate = ItemDate;
}
}";
$conds = array( 'ItemID' => (int) $id );
$results = $db->items->group($keys, $initial, $reduce,
array('condition'=> $conds ) );
我已经尝试了一些东西,但似乎不起作用...
$map = new MongoCode("function() {
emit(this.ItemID,this.ItemDate);
}");
$reduce = new MongoCode("function(obj, prev) {
if(prev.myLastDate < obj.ItemDate) {
prev.myLastDate = obj.ItemDate;
}
}");
$items = $db->command(array(
"mapreduce" => "items",
"map" => $map,
"reduce" => $reduce,
"query" => array("ItemID" => $id);
$results = $db->selectCollection($items['result'])->find();
你能帮忙吗?
解决方案
您不需要为此使用 map/reduce。如果您的日期字段包含 ISODate,一个简单的查询就可以了:
db.yourColl.find({},{_id:0,ItemDate:1}).sort({ItemDate:-1}).limit(1)
为了有效地完成此查询,您需要在 ItemDate
上设置索引
db.yourColl.createIndex({ItemDate:-1})
解释
查询
让我们剖析查询。 db.yourColl
......
-
.find({}
默认查询 -
,{_id:0,ItemDate:1}
我们只希望ItemDate
被退回。这称为投影。 -
.sort({ItemDate:-1})
返回的文档应按 ItemDate 的降序排序,使具有最新日期的文档首先返回。 -
.limit(1)
由于我们只想要最新的,因此我们将结果集限制为它。
索引
我们按降序创建索引,因为这是您将使用它的方式。但是,如果需要将默认查询更改为其他内容,则创建的索引应按确切顺序包含查询中检查的所有字段。