【问题标题】:How can I know in mongodb if a field is a Date type?如果字段是 Date 类型,我如何在 mongodb 中知道?
【发布时间】:2012-09-19 04:14:41
【问题描述】:

我正在开发一个 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" 结果吗?

【问题讨论】:

  • 您是否将带有myDate 的文档作为其他类型添加到其他地方?我猜我对你在这里想要完成的事情感到困惑。
  • 没有。我总是使用相同的结构。我理解你的问题,这都是因为我的 webapp 需要从多个集合中获取数据,并且集合是由其他应用程序动态创建的,然后......我的 webapp 永远不知道每个集合背后的架构。我希望它有助于澄清我的想法。
  • 如果您改为运行db.user.myDate instanceof ISODate 会怎样?我认为 node.js 直接在它的驱动程序中翻译ISODate
  • 您使用 JSON 解析器,日期将没有对象类型,它只是一个对象......因为 JSON 无法以真实形式容纳对象。在日期对象中应该有一个名为 $date 的子字段,检查一下。
  • 当您调用 JSON stringify 时,日期对象使用 JSON.stringify(a) 更改为字符串 var a = {a:new Date()} 变为 '{"a":"2012-09 -28T11:05:56.163Z"}'。您必须检查实际的 bson 类型而不是 json 字符串化/解析的对象,这会将其减少为 JSON 支持的基本 javascript 类型(并且 Date 不是其中之一)

标签: node.js mongodb date


【解决方案1】:

我终于找到了解决办法。

正如@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"

我还是不明白为什么。

【讨论】:

  • 最后一部分,在 Mongo 控制台中,返回 false,因为 db.user 是集合类型,并且由于控制台访问对象的方式(通过 PHP 中的魔术),日期字段总是作为有效对象,但作为具有 std 类类型的空对象。因此,当您进行游标查找时,db.user 将永远不会仅查询集合对象中的文档的字段类型。
【解决方案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);
    });
});

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

【讨论】:

  • 我做到了,直接在 mongo 客户端控制台上。我又做了一次,而且..它是一样的。它返回false,为什么?我正在使用 v2.0.4
  • 无论如何,我将在我的帖子中添加更多信息,以澄清我在另一部分所做的事情,nodejs
  • ` 但对我来说,查询您不知道其架构的集合似乎是不明智的。`这不是 MongoDB 无架构设计的重点吗?
  • 在某种程度上,但在生产环境中,最好知道数据库中有哪些字段、哪些类型
  • 谢尔曼,我不明白。复制您的代码,它对我返回 false。 (!?!?!!?)
【解决方案3】:

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

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

你可以通过两种方式解决:

  • 在检查字段类型之前不要转换为 JSON
  • 每个对象都有属性。日期没有什么不同,它应该有一个$date 属性(我相信),您可以检查isset 以查看该字段是否为日期类型

【讨论】:

  • 非常有趣。我打算改变它,但我意识到(你会在下一个答案中看到)一旦我从数据库中获取对象,我就会失去它的类型......我会继续战斗
  • @larrytron 确实很有趣,您不应该在控制台中丢失对象类型。你用什么来挑选和迭代控制台中的文档?
  • 在控制台中,正如我所发布的,typeof db.user.myDate --> It returns "Object" db.user.myDate instanceof Date --> It returns "false"
  • 但是,如果我这样做:db.user.find({myDate: {$type: 9}}) 它返回结果,所以,这意味着是日期。不是吗?
  • @larrytron 确实如此,啊这真是令人困惑:S
【解决方案4】:

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

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

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

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

【讨论】:

  • 对不起,伙计,但我不明白你的想法。我所做的是从集合中获取记录,并逐个字段分析,并根据字段类型执行特定操作。我的问题是我得到的是字符串类型而不是日期类型。我正在使用 node-mongodb-native 驱动程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 2012-10-29
相关资源
最近更新 更多