7

我正在开发一个 NodeJS+Mongodb 应用程序。

我刚刚使用控制台客户端将一条记录插入 mongodb:

db.user.save({myId:11111, myDate: ISODate("2012-04-30T00:00:00.000Z")})

问题是,当我在 node.js 中时,我需要知道“myDate”字段是否真的是 Date 类型,以便执行数据范围查询等。

我尝试了以下。

1.在mongo客户端控制台上:

typeof db.user.myDate --> It returns "Object"
db.user.myDate instanceof Date --> It returns "false"

2. 在我的 Nodejs 代码上,

我正在尝试获取调用此getTypeMembers函数的类型。(来自 db 查询的 obj)

exports.getTypeMembers = function(obj) {
obj = JSON.parse(JSON.stringify(obj)

for(var _k in obj){
    if(Object.prototype.toString.call(obj[_k]) === '[object Array]' ) {
        obj[_k] = "Array";
    }
    else if(typeof(obj[_k])=="object"){
        obj[_k] = this.getTypeMembers(obj[_k]);
    }else{
        obj[_k] = typeof (obj[_k]);
    }
}
return obj;

};

我在这种方法中得到的是:"String",当我需要时"Date"

有没有其他方法可以获得某种"Date"结果?

4

4 回答 4

4

您可以使用 $type 运算符来查询特定类型的字段:

db.col.query({a: {$type: 9}})

9 是日期类型的数字,请参阅 http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24type

至于确定 node.js 内部的类型,这取决于您的驱动程序。我没有使用过,但它可能是一个特定的原型,就像 ObjectId 一样。也许您可以检查对象并查找构造函数名称。

于 2012-09-27T11:43:25.930 回答
4

我终于找到了我的解决方案。

正如@christkv 所说,一旦您调用 JSON 字符串化,所有原始类型肯定会丢失。所以,以这种方式思考,我的方法getTypeMembers非常适合我。

请注意,obj参数来自数据库,并且直接省略了“_id”(mongodb标识符)以避免执行递归函数时出现问题:

exports.getTypeMembers = function(obj) {
    for(var _k in obj){
        if (_k =="_id") continue;
        if (Object.prototype.toString.call(obj[_k]) === "[object Number]"){
            obj[_k] = "Number";
        }else if (Object.prototype.toString.call(obj[_k]) === "[object String]"){
            obj[_k] = "String";
        }else if (Object.prototype.toString.call(obj[_k]) === "[object Date]"){
            obj[_k] = "Date";
        } else if(Object.prototype.toString.call(obj[_k]) === '[object Array]' ) {
            obj[_k] = "Array";
        } else if(typeof(obj[_k])=="object"){
            obj[_k] = this.getTypeMembers(obj[_k]);
        } else{
            obj[_k]  = (typeof obj[_k])[0].toUpperCase() + (typeof obj[_k]).slice(1);
        }
    }
    return obj;
};

在 Mongo 控制台部分,我只能获得执行以下操作的类型:

db.user.find({},{myDate:1}).forEach(function(f) { print (f.myDate instanceof Date) } );

但如果我这样做,

typeof db.user.myDate --> It returns "Object"
db.user.myDate instanceof Date --> It returns "false"

我仍然不明白为什么。

于 2012-10-01T09:30:03.727 回答
2

我对使用有点困惑

db.user.myDate

在你的例子中。您是否正在对 node-mongodb-native 给您的 Db 对象进行精确调用?如果是这样,您应该得到未定义,因为您实际上并没有查询数据库,而是检查 Db javascript 对象的属性(几乎可以肯定的属性不存在)。

您能否发布您从 node.js 进程运行的代码?我使用相同的 shell 插入测试了您的代码,一旦我从 node.js 中的数据库中检索到文档,

doc.myDate instanceof Date

返回真。

我也不熟悉您的应用程序,但对我来说,查询您不知道数据类型的集合似乎是不明智的。为什么您不确定其他应用程序对 myDate 字段使用什么类型的值?

编辑:

var coll = new mongo.Collection(client, 'user');
    coll.find({}).toArray(function(err, docs) {
    docs.forEach(function (doc) {
        console.log(doc);
        console.log(doc.myDate instanceof Date);
    });
});

在将相同的外壳插入到您的外壳后,在 nodejs 中运行时为我记录“真”。如果你运行它会发生什么?

于 2012-09-27T14:26:08.047 回答
1

从您最近的编辑来看,我相信我看到了问题。您正在将文档解析为 JSON。与 BSON 不同,JSON 不支持 BSON 对象的文字创建和存储。该ISODate对象是 BSON 数据类型。

因此,当您转换为 JSON 时,您实际上会丢失此对象。

您可以通过两种方式解决此问题:

  • 在检查字段类型之前不要转换为 JSON
  • 每个对象都有属性。Date 没有什么不同,它应该有一个$date属性(我相信),您可以检查该属性是否isset为 date 类型
于 2012-09-27T18:15:05.080 回答