我很惊讶地看到_id
不是唯一索引。我正在为_id
字段提供值,而MongoDB正在创建一个索引,但它并不是唯一的。我尝试更新它(通过在_id
字段上创建一个新的唯一索引),但没有任何改变。我也没有得到任何错误。为什么会发生这种情况?如何在_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=test@gmail.com}
日志中转储的索引(为简洁起见省略了时间戳等)。我不确定为什么每个索引都打印两次,但这是另一个问题的问题。对于记录,这就是我打印索引的方式: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 :(得分:1)
在mongo课程视频中,声明“_id”索引未使用命令db.collection.getIndexes()
标记为唯一,即使 唯一。
我在官方文档中找不到这些信息。
如果您想确定,请尝试添加另一个包含现有_id
字段的文档。
我的_id
索引未标记为唯一:
> db.products.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.products"
}
]
添加现有索引并获取duplicat键错误:
> 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') }"
}
})
答案 1 :(得分:0)
_id
字段不仅足以确保唯一性,该字段也必须是ObjectId
类型。我的问题是我将字段插入为String
。
那就是说,我现在遇到的问题是所有插件都不起作用。没有错误,没有索引违规但文档根本没有插入。请参阅下面的更新代码,该代码始终输入第二种情况(writeResult.getN
为0):
编辑:原来失败的插件实际上并没有失败。根据{{3}} 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
}