我想为数组的最后一个元素定义唯一索引?这在 mongo 中可能吗?
只有status[this.status.length-1].state
和user_id
对于特定的status.state
(例如活跃)必须是独一无二的。
注意:状态数组的最后一个元素定义用户的当前状态。
例如:2 user_id 和 status[this.status.length-1].state: **revoked**
状态可以存在。但 2 个带有 status[this.status.length-1].state: **active**
的 user_id 不能存在。
{
"_id" : ObjectId("59a609778c6929e7122322cf"),
"user_id": '9e2cZ'
"status" : [
{
"state" : "active",
"updatedAt" : ISODate("2017-08-30T21:23:21.158Z"),
"createdAt" : ISODate("2017-08-30T21:23:21.158Z")
},
{
"updatedAt" : ISODate("2017-08-31T22:24:02.613Z"),
"createdAt" : ISODate("2017-08-31T22:24:02.613Z"),
"state" : "revoked"
},
{
"updatedAt" : ISODate("2017-08-31T22:25:02.888Z"),
"createdAt" : ISODate("2017-08-31T22:25:02.888Z"),
"state" : "active"
}
],
}
最佳答案
索引数组元素
我知道执行此操作的唯一方法是扭转您的问题。 最新状态应该位于数组的第一个位置。 您可以使用 unshift function 插入它。并以这种方式创建索引:
db.coll.createIndex({user_id:1, 'status.0.state': 1})
这将为数组的第一个元素建立索引。
以下是显示索引使用的说明:
db.coll.find({user_id: 1, 'status.0.state': "active"}).explain().queryPlanner.winningPlan
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"user_id" : 1,
"status.0.state" : 1
},
"indexName" : "user_id_1_status.0.state_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"user_id" : [ ],
"status.0.state" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"user_id" : [
"[1.0, 1.0]"
],
"status.0.state" : [
"[\"active\", \"active\"]"
]
}
}
}
要在 Node 中插入您的状态,您应该转动
user.status.push(newStatus);
进入
user.status.unshift(newStatus);
具有部分索引的唯一索引
为了使事件状态具有唯一性,您可以将先前的答案与部分索引结合起来。 部分索引将仅活跃用户建立索引。
这是索引创建命令:
db.users.createIndex(
{user_id:1, 'status.0.state': 1},
{unique: true, partialFilterExpression: {"status.0.state": {$eq: 'active'}}}
)
然后,我插入 2 个用户,一个活跃,一个不活跃
> db.users.find().pretty()
{
"_id" : ObjectId("59a609778c6929e7122322cd"),
"user_id" : "9e2cZ",
"status" : [
{
"state" : "inactive",
"updatedAt" : ISODate("2017-08-30T21:23:21.158Z"),
"createdAt" : ISODate("2017-08-30T21:23:21.158Z")
},
{
"updatedAt" : ISODate("2017-08-31T22:24:02.613Z"),
"createdAt" : ISODate("2017-08-31T22:24:02.613Z"),
"state" : "revoked"
},
{
"updatedAt" : ISODate("2017-08-31T22:25:02.888Z"),
"createdAt" : ISODate("2017-08-31T22:25:02.888Z"),
"state" : "active"
}
]
}
{
"_id" : ObjectId("59a609778c6929e7122322cf"),
"user_id" : "9e2cZ",
"status" : [
{
"state" : "active",
"updatedAt" : ISODate("2017-08-30T21:23:21.158Z"),
"createdAt" : ISODate("2017-08-30T21:23:21.158Z")
},
{
"updatedAt" : ISODate("2017-08-31T22:24:02.613Z"),
"createdAt" : ISODate("2017-08-31T22:24:02.613Z"),
"state" : "revoked"
},
{
"updatedAt" : ISODate("2017-08-31T22:25:02.888Z"),
"createdAt" : ISODate("2017-08-31T22:25:02.888Z"),
"state" : "active"
}
]
}
它有效,我有 2 个用户具有相同的 user_id 但状态不同。
如果我尝试插入具有相同 user_id 的另一个事件用户,则会失败:
> db.users.insert({user_id: '9e2cZ', status: [{state: 'active'}]})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.users index: user_id_1_status.0.state_1 dup key: { : \"9e2cZ\", : \"active\" }"
}
})
这样,您就拥有了基于数组第一个元素的唯一索引。
关于node.js - 如何在 Mongo 中为数组的元素定义唯一索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46162283/