我有一个使用数值作为_id
的Mongoose架构,例如102375848308956134094
。当我将集合和findById
保存在Mongoose或find({ _id: 102375848308956134094 });
Mongo shell中时,会返回正确的文档,但_id
与先前提供的文档不同(而不是102375848308956140000
)。
这是一个问题,好像我要保存一个集合_id
102375848308956134095
(注意最后一个数字从4
更改为5
),MongoDB错误输出(E11000 duplicate key error index... dup key: { : 1.023758483089561e+20
)。
MongoDB是否将Number
视为浮点数?
以下是一个示例查询:
> db.users.find({ _id: 102375848308956134094 }).pretty();
{
"_id" : 102375848308956140000,
"access_token" : "",
"access_token_expires" : ISODate(""),
"given_name" : "Jonathon",
"refresh_token" : ""
}
注意:我删除了access_token
等值。
但是,当保存该文档时,我绝对将_id
值指定为102375848308956134094
。
任何想法发生了什么?
这是我的架构:
/*jslint es5: true, indent: 2, node:true, nomen: true, maxlen: 80, vars: true*/
'use strict';
module.exports = function (mongoose) {
var Schema = new mongoose.Schema({
_id: Number,
access_token: String,
access_token_expires: Date,
given_name: String,
refresh_token: String
});
return mongoose.model('User', Schema);
};
这是upsert
:
...
models.user.update(
{
_id: user.id
},
{
access_token: access_token,
access_token_expires: new Date(Date.now() + (59 * 60 * 1000)),
given_name: user.given_name,
refresh_token: refresh_token
},
{
upsert: true
},
/*TODO: Handle upsert errors*/
function (err, numberAffected, raw) {
if (err) {
console.log(err);
} else {
delete req.session.state;
req.session._id = user.id;
res.redirect('/');
}
}
);
...
所有的帮助,一如既往,非常感谢!
/ 修改 /
我已经尝试过@ JohnnyHK使用Long
数字的答案,但_id
似乎仍未正确存储在文档中。它将_id
保存为-8304616133301175602
而不是102375848308956134094
。我已经对find
文档进行了多次查询,但只提供_id
作为-8304616133301175602
返回正确的文档,例如
> db.users.find().pretty();
{
"_id" : NumberLong("-8304616133301175602"),
"access_token" : "ya29.1.AADtN_VyfAvBlam2HCERpI0JcJkcwg22t1124tZw0G7pgRyTcaIuGU-dX3H4Q-M",
"access_token_expires" : ISODate("2013-12-09T12:42:53.098Z"),
"given_name" : "Jonathon",
"refresh_token" : "1/-2GQ_s3JogCr45Z1CBKWBHTEcjE0Nda9xkpFFdl7wT0"
}
> db.users.find({ _id: 102375848308956134094 }).pretty();
> db.users.find({ _id: NumberLong(102375848308956134094) }).pretty();
> db.users.find({ _id: NumberLong('102375848308956134094') }).pretty();
Mon Dec 9 11:46:26.433 Error: could not convert "102375848308956134094" to NumberLong
> db.users.find({ _id: -8304616133301175602 }).pretty();
{
"_id" : NumberLong("-8304616133301175602"),
"access_token" : "",
"access_token_expires" : ISODate(""),
"given_name" : "Jonathon",
"refresh_token" : ""
}
有关为何会这样做的任何想法?
答案 0 :(得分:0)
Number
模式类型是64位浮点数,它没有足够的分辨率来准确表示102375848308956134094,因此它最终舍入为102375848308956140000。
一种解决方案是使用mongoose-long
插件(由Mongoose的作者创建),以便您可以为_id
使用64位整数,如下所示:
var Schema = new mongoose.Schema({
_id: {SchemaTypes.Long},
access_token: String,
access_token_expires: Date,
given_name: String,
refresh_token: String
});
<强>更新强>
您的数字_id
值实际上大于64位,因此如果您不能将它们缩小,则必须使用字符串。
var Schema = new mongoose.Schema({
_id: String,
access_token: String,
access_token_expires: Date,
given_name: String,
refresh_token: String
});