MongoDB的BSON“_id”看起来像Node.js中的科学记数法

时间:2013-09-04 22:42:49

标签: node.js mongodb mongoose

偶尔我会得到一个带有_id值的文档,javascript可以并且确实解释为科学记数法。

仅说明我运行以下查询的问题。

  

db.users.find({$ where:'this._id> 1'})。count()

2

此集合中有数百个文档,但那些评估为数字的文档在{$ in:[]}子句中使用时会产生问题。

  

db.users.findOne({$ where:'this._id> 1'})._ id

ObjectId(“5225141850742e0000002331”) - 看到它看起来像科学记数法吗?

当我想将_id作为字符串存储在另一个集合中时,我认为我遇到了麻烦,比如

friendsCollection: { _uid: “5225141850742e0000002331” //这里有更多属性 }

当我检索该值时,Node(或Mongoose)会将其解释为“Infinity”之类的数字。然后我的代码最终尝试使用{_id:{$ in:[Infinity]}}搜索用户,这会引发错误。

我猜测有一种更健壮的方法来存储_id值或处理你知道为_ids的属性,但我不知道如何。

3 个答案:

答案 0 :(得分:3)

从十六进制字符串转换为ObjectID的二进制表示

如果要将_id值的24字节十六进制字符串表示转换为存储在MongoDB中的二进制ObjectID,可以使用 ObjectID.createFromHexString

// Need to require ObjectID class if not already included
ObjectID = require('mongodb').ObjectID;

var uid = ObjectID.createFromHexString("5205c4bd7c21105d0d99648c")

比较ObjectID

您应该使用$gt operator进行ObjectID比较,而不是$where$where运算符计算JavaScript字符串,无法利用索引;它的性能要低得多(特别是对于这个用例)。

因此,找到大于给定ObjectID的findOne()的{​​{1}}示例应改为:

_id

要获得有关查找下一个更高的ObjectID的可预测结果,您应使用db.users.findOne( { _id: { $gt: ObjectID("5205c4bd7c21105d0d99648c") } } )._id find()以及sort指定显式排序顺序:

limit

您会注意到这些查找示例未明确调用// Find next _id greater than ObjectID("5205c4bd7c21105d0d99648c") db.users.find( {_id: { $gt: ObjectID("5205c4bd7c21105d0d99648c") } } ).sort({_id:1}).limit(1).toArray()[0]._id 。默认的createFromHexString构造函数将尝试根据给定值是24字节十六进制字符串,12字节二进制字符串还是数字来创建适当的ObjectID()。如果您知道要提供的是什么类型的值,最好调用预期的构造函数来限制意外的转换(例如,如果您不小心提供了数字而不是十六进制字符串)。

数据库引用(DBRefs)

MongoDB显式不支持连接,但是当您希望将相关文档的ObjectID存储为另一个文档中的引用时,存在用于存储数据库引用(DBRefs)的约定。 Mongoose有一个_id选项,简化了引用的工作;请参阅Mongoose文档中的'Population'

答案 1 :(得分:0)

在某些时候,我在使用本机驱动程序查询_id时遇到了问题。我在查询中使用ObjectId修复了它。您可能会发现这有用:

var ObjectId = require("mongodb").ObjectID;

query._id = { $gt: ObjectId(idString) }

答案 2 :(得分:0)

啊,也许我应该在我的模式中使用Mongoose数据类型“ObjectId”。

例如,我使用的是像这样的mongoose模式:

locations:{
    _uid:{type:String},//<--probably not good
    lat:{type:Number},
    lng:{type:Number}
},

开始使用Schema类型“ObjectId”:

locations:{
    _uid:Schema.Types.ObjectId,//<--better?
    lat: {type:Number},
    lng: {type:Number}
},

我必须重建大量数据才能支持这一变化。此外,我不会确定,直到另一个科学记数字_出现,(我删除了有问题的文档)。然而,这种接缝很有希望。