我想为数组的最后一个元素定义一个唯一索引?甚至可能在mongo?
status[this.status.length-1].state
只有user_id
和specific status.state
(例如有效)必须是唯一的。
注意:状态数组的最后一个元素定义了用户的当前状态。
例如:可以存在2个具有status[this.status.length-1].state: **revoked**
状态的user_id。但是不能存在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"
}
],
}
答案 0 :(得分:2)
我知道执行它的唯一方法是扭转你的问题。 最新状态应位于阵列的第一个位置。 您可以使用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\"]"
]
}
}
}
要在节点中插入您的状态,请转为
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\" }"
}
})
这样,您就拥有了一个基于数组第一个元素的唯一索引。