node.js - 如何在 Mongo 中为数组的元素定义唯一索引

标签 node.js mongodb mongoose

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

只有status[this.status.length-1].stateuser_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/

相关文章:

node.js - Mongoose 鉴别器 : NodeJS/Express

javascript - Mongoose 不会保存大文本

node.js - 我想根据德语和英语显示国家/地区列表

MongoDB获取字段值的长度

node.js - 查询时node-influx的内存使用情况

arrays - 如何访问mongodb数组中的元素

mongodb - 无法识别的字段: 'ntoreturn' error in documenDB

javascript - 制作一个过滤器: Interaction between script and node app

css - 我可以在 stylus 中将变量放入文字 css 中吗?

json - Package.json - 无法安装模块