如何为Mongo中的一个元素定义一个唯一索引

我想为数组的最后一个元素定义一个唯一索引? 这在mongo中甚至可能吗?

只有status[this.status.length-1].stateuser_id对于specific 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" } ], } 

索引一个数组元素

我知道执行它的唯一方法是扭转你的问题。 最新的状态应该在你arrays的第一位。 您可以使用不移位function来插入它。 并用这种方式创build你的索引:

 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); 

具有部分索引的唯一索引

要在活动状态上具有唯一性,可以将以前的答案与部分索引结合使用。 部分索引将索引活动用户。

这里是索引创build命令:

 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\" }" } }) 

这样,你有一个基于数组的第一个元素的唯一索引。