0

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

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

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

2

这个集合中有数百个文档,但是当它们在 {$in:[]} 子句中使用时,那些评估为数字的 2 个会导致问题。

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

ObjectId("5225141850742e0000002331") - 看到它看起来像科学记数法吧?

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

FriendsCollection: { _uid:"5225141850742e0000002331" //这里有更多属性 }

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

我猜有一种更强大的方法来存储_id 值或处理您知道是_ids 的属性,但我不知道如何。

4

3 回答 3

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运算符进行 ObjectID 比较,而不是$where. 运算符评估 JavaScript 字符串,$where不能利用索引;它的性能会低得多(特别是对于这个用例)。

因此findOne(),查找_id大于给定 ObjectID 的示例应改为:

db.users.findOne(
    { _id: { $gt: ObjectID("5205c4bd7c21105d0d99648c") } }
)._id

对于查找下一个更高 ObjectID 的可预测结果,您应该使用find()withsort和指定明确的排序顺序limit

// Find next _id greater than ObjectID("5205c4bd7c21105d0d99648c") 
db.users.find(
    {_id: { $gt: ObjectID("5205c4bd7c21105d0d99648c") } }
).sort({_id:1}).limit(1).toArray()[0]._id

您会注意到这些 find 示例没有显式调用createFromHexString. 默认构造函数将尝试根据给定值是 24 字节十六进制字符串、12 字节二进制字符串还是数字ObjectID()来创建适当的值。ObjectID如果你知道你提供了什么样的值,最好调用预期的构造函数来限制意外的转换(例如,如果你不小心提供了一个数字而不是一个十六进制字符串)。

数据库引用 (DBRefs)

MongoDB 明确不支持连接,但是当您想要将相关文档的引用存储为另一个文档中的引用时,有一个存储数据库引用 (DBRefs)的约定。_idMongoose 有一个ref选项可以简化引用的工作;请参阅Mongoose 文档中的“人口”

于 2013-09-09T04:43:45.237 回答
0

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

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

query._id = { $gt: ObjectId(idString) }
于 2013-09-05T06:38:14.600 回答
0

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

例如,我使用的是这样的猫鼬模式:

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

开始使用模式类型“ObjectId”:

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

我必须重建大量数据来支持这种变化。另外,直到弹出另一个科学记数法_id,我才能确定(我删除了有问题的文档)。然而,这看起来很有希望。

于 2013-09-12T15:43:11.177 回答