偶尔我会得到一个带有_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的属性,但我不知道如何。
答案 0 :(得分:3)
如果要将_id
值的24字节十六进制字符串表示转换为存储在MongoDB中的二进制ObjectID,可以使用 ObjectID.createFromHexString :
// Need to require ObjectID class if not already included
ObjectID = require('mongodb').ObjectID;
var uid = ObjectID.createFromHexString("5205c4bd7c21105d0d99648c")
您应该使用$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()
。如果您知道要提供的是什么类型的值,最好调用预期的构造函数来限制意外的转换(例如,如果您不小心提供了数字而不是十六进制字符串)。
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}
},
我必须重建大量数据才能支持这一变化。此外,我不会确定,直到另一个科学记数字_出现,(我删除了有问题的文档)。然而,这种接缝很有希望。