使用 _id 为日期查询条件

use _id be to a date query condition

我知道 _id 字段可以转换成日期。
这是函数:

ObjectId.prototype.getTimestamp = function() {
  return new Date(parseInt(this.toString().slice(0,8), 16)*1000);
}

然后我可以使用 doc._id.getTimestamp(); 来显示文档的创建日期时间。

事实是,文档只有 _id 与日期相关的字段。 我的问题是:如何只通过_id?

查询特定日期范围内的文档
function GetTimeID(yourTime){
    yourTime = new Date(yourTime);
    yourTime = Math.floor(yourTime/1000).toString(16);
    var newID = ObjectId(yourTime + "0000000000000000");
    return newID;
}

var firstDateID = GetTimeID("1/1/2015");
var secondDateID = GetTimeID("1/1/2015");

var batList = batmanCollection.find({_id: {$gt: firstDateID }}).toArray();

var batList = batmanCollection.find({_id: {$lt: secondDateID }}).toArray();

var batList = batmanCollection
    .find({_id: {$lt: firstDateID , $gt: secondDateID }}).toArray();

可以使用$where发送JavaScript到服务器进行查询。但是忘记原型,因为所有逻辑都必须是自包含的或以其他方式加载到服务器。这意味着它必须在函数中进行评估:

db.collection.find(function() {
    return 
        ( new Date(parseInt(this._id.toString().slice(0,8), 16)*1000)
           > new Date("2015-01-01") ) &&
        ( new Date(parseInt(this._id.toString().slice(0,8), 16)*1000)
           < new Date("2015-02-01") );
})

但这不是一个好主意,因为 $where 不能使用 "index" 来过滤匹配项。

您最好创建一个包含实际日期对象的 "timestamp" 字段并使用 $lt and $gt 运算符本身。该实际字段可以被索引,操作员将使用它来进行选择。

另一种方法是找出查询之外的 ObjectId 值,然后使用标准运算符:

var start =  ObjectId(
    (new Date("2015-01-01").valueOf() / 1000).toString(16) + "0000000000000000")
 ),
    end =  ObjectId(
     (new Date("2015-02-01").valueOf() / 1000).toString(16) + "0000000000000000")
 );

db.collection.find({ "_id": { "$gt": start, "$lt": end } })

根据日期创建 ObjectId 值,并允许您使用始终存在的主键索引。

有些驱动程序甚至在其 ObjectId 实现中支持 "create from timestamp" 方法。