2013-12-08 81 views
0

我有一個使用數值作爲_id(例如,)的Mongoose模式。 102375848308956134094。當我將Mongoose中的集合和findByIdfind({ _id: 102375848308956134094 });保存在Mongo Shell中時,雖然_id與之前提供的文檔(而不是它的102375848308956140000)不同,但返回了正確的文檔。保存到集合中時傳入更新的數字發生更改(MongoDB)

這是一個問題,因爲如果我是救一個集合的_id102375848308956134095(注意最後一位從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" : "" 
} 

NB:我已刪除了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('/'); 
    } 
    } 
); 

... 

所有幫助,一如既往,非常感謝!

/編輯/

我已經嘗試了@但是使用Long數字JohnnyHK的回答,_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

Number模式類型是64位浮點,其不具有足夠的分辨率來準確地表示102375848308956134094,所以它最終四捨五入至102375848308956140000.

一種解決方案是使用mongoose-long插件(創建由貓鼬的作者),這樣就可以使用64位整數你_id這樣的:

var Schema = new mongoose.Schema({ 
    _id: {SchemaTypes.Long}, 
    access_token: String, 
    access_token_expires: Date, 
    given_name: String, 
    refresh_token: String 
}); 

UPDATE

您的數字_id值實際上大於64位,因此如果不能使它們變小,則必須使用字符串。

var Schema = new mongoose.Schema({ 
    _id: String, 
    access_token: String, 
    access_token_expires: Date, 
    given_name: String, 
    refresh_token: String 
}); 
+0

我覺得這樣的事情正在發生。謝謝!它會導致任何問題將_id存儲爲String。除了顯然沒有錯誤會被拋出,如果我試圖插入一個字符串。我沒有對數字做任何計算,所以除了可能是性能問題之外,我看不到問題?我來自MySQL背景,其中不同類型的數據消耗不同的空間量和性能可能受到影響。對此有何想法? –

+0

@JonathonOates將它存儲爲字符串可以正常工作,但效率會低得多,因爲它的字符數爲2個字節;所以對於64位整數來說,42個字節而不是8個。您仍然可以將Long值作爲字符串傳遞,Mongoose會在實際與數據庫進行交互時爲您轉換,因此我將使用Long。 – JohnnyHK

+0

'Long'似乎'被錯誤地存儲在集合中,除非查詢存儲爲'_id'的確切(不正確)數字,否則我無法'查找'記錄。我將用一個例子編輯我的問題:-) –

相關問題