2015-09-07 93 views
0

我很驚訝地看到_id不是一個獨特的索引。我爲_id字段提供了值,MongoDB創建了一個索引,但它不是唯一的。我試圖更新它(通過在_id字段上創建一個新的唯一索引),但沒有任何改變。我也沒有得到任何錯誤。爲什麼會發生這種情況,我如何才能在_id上創建唯一索引?爲什麼Casbah/MongoDB id索引不唯一?

MongoDB版本(由version()給出)3.0.6,Casbah版本2.8.2,Scala版本2.11.7。

我的文檔結構:

{_id=1, firstName=John, lastName=Doe, phoneNum=111-111-1111, active=true, [email protected]}

指數作爲日誌轉儲(時間戳等爲簡潔起見省略)。我不確定每個索引爲什麼要打印兩次,但這是另一個問題的問題。對於記錄,這是我如何打印索引:collection.indexInfo.foreach { index => logger.debug(s"Index: ${index.toMap}") }

Index: {v=1, key={ "_id" : 1}, name=_id_, ns=akka.users} 
Index: {v=1, unique=true, key={ "phoneNum" : 1}, name=phoneNum_1, ns=akka.users} 
Index: {v=1, unique=true, key={ "email" : 1}, name=email_1, ns=akka.users, sparse=true} 
Index: {v=1, key={ "_id" : 1}, name=_id_, ns=akka.users} 
Index: {v=1, unique=true, key={ "phoneNum" : 1}, name=phoneNum_1, ns=akka.users} 
Index: {v=1, unique=true, key={ "email" : 1}, name=email_1, ns=akka.users, sparse=true} 

回答

0

一個燈泡熄滅了。原來Mongo爲了保證唯一性而在文檔中有一個獨特的_id字段,該字段也必須是ObjectId。我的問題是我插入字段爲String

這就是說,我現在有問題,沒有插入的工作。沒有錯誤,沒有索引違規,但文檔沒有插入。看到我下面更新的代碼總是進入第二種情況(writeResult.getN是0):

編輯:原來,失敗的插入沒有實際失敗。根據this SO帖子,Java驅動程序總是返回0插入的行數。所以除非有例外,否則總是假定插入是成功的。

override def createUser(user: User) = { 
    val dbObj = userToDbObj(user) 

    val result = Try(collection.insert(dbObj, WriteConcern.Safe)) 

    val newUser = user.copy(userId = Some(dbObj.get(USER_ID).toString)) 

    result match { 
    case Success(writeResult) if (writeResult.getN == 1) => Some(newUser) 
    case Success(writeResult) => 
     logger.error(s"Failed to create user: ${newUser}, write result: ${writeResult}."); None 
    case Failure(ex) => logger.error("Failed to create user.", ex); None 
    } 
} 

private def userToDbObj(user: User) = { 
    val builder = MongoDBObject.newBuilder 

    builder += USER_ID -> (user.userId match { 
    case Some(userId) if (ObjectId.isValid(userId)) => logger.info("Using given user id."); new ObjectId(userId) 
    case _ => logger.info("Generating new user id."); new ObjectId() 
    }) 

    builder += (FIRST_NAME.toString -> user.firstName, 
    LAST_NAME.toString -> user.lastName, 
    PHONE_NUM.toString -> user.phoneNum) 

    user.email match { 
    case Some(email) => builder += EMAIL.toString -> user.email.get 
    case _ => 
    } 

    builder.result 
} 
1

在蒙戈的課程視頻,更說明使用命令db.collection.getIndexes()即使「_id」指數不標記爲唯一獨特。 我在官方文檔中找不到這些信息。

如果您想確定,請嘗試使用現有的_id字段添加另一個文檔。

_id指數未標記的獨特之處:

> db.products.getIndexes() 
[ 
     { 
       "v" : 1, 
       "key" : { 
         "_id" : 1 
       }, 
       "name" : "_id_", 
       "ns" : "test.products" 
     } 
] 

加入現有的索引,並獲得duplicat關鍵錯誤:在我的腦海,當我看到@ codename44插入語句以上

> db.products.insert({ "_id" : ObjectId("55ed6ccc20a18b075ba683b2")}) 
WriteResult({ 
     "nInserted" : 0, 
     "writeError" : { 
       "code" : 11000, 
       "errmsg" : "E11000 duplicate key error index: test.products.$_id_ dup key: { : ObjectId('55ed6ccc20a18b0 
75ba683b2') }" 
     } 
}) 
+0

我在發佈前檢查過,它允許插入。我發現了這個問題,請看下面的答案。我會盡快答覆你的答案,但不是正確答案。 –

相關問題