MongoDB对集合中的文档执行复杂约束

比方说,我有一个名为Users的集合中的文档,如下所示:

{ name: 'vic', <-- unique index ownedItems: ['paperclip-1252', 'stapler-1337'] } 

ownedItems是一些其他Items集合中唯一索引的标识符的数组。 现在,可以说我想添加一个元素到ownedItems数组中,但是我想强制执行这样的规则:不能更新用户的ownedItems数组,以便导致包含相同项目的多个用户文档标识符在其ownedItems数组中。

也就是说,我想执行:

 db.Users.updateOne( { name: 'vic'}, { $set: { ownedItems: [ 'paperclip-1252', 'stapler-1337', 'notebook-42' ] } }) 

…只有在没有其他用户文档具有包含“notebook-42”(或“paperclip-1252”或“stapler-1337”)的ownedItems数组的情况下才能成功。

我可以做一个查询来检查,除了vic之外,还有其他的用户是否拥有被提议ownedItems数组中的任何项目,如下所示:

 db.Users.find({ $and: [ { ownedItems: { $in: ['paperclip-1252', 'stapler-1337','notebook-42'] } }, { name: { $ne: 'vic' } } ] }) 

…只有在没有结果的情况下才进行更新。 然而谁说,在我得到这个答案之间的时间,当我执行我的更新,答案没有改变(例如,因为有人插入'笔记本42'到他们ownedItems)?

我怎样才能primefaces执行该查询,然后基于结果更新文档? 虽然我已经使用MongoDB CLI语法描述了这一点,但是我会,而不是在使用mongodb包的NodeJS应用程序中实现这个逻辑,以防万一。

唯一的索引是我能想到的,在Mongodb中可以应用交叉文档约束的唯一方法,在这种情况下恰好工作。

ownedItems上创build一个唯一的索引。 Mongo将会对每个设定值进行索引,而不是集合本身。

为了允许重复的空数组(ab)使用sorting顺序为null和空logging在填充数组之前。

 db.Users.createIndex({ ownedItems: 1 }, { unique:1, partialFilterExpression: { ownedItems: { $gt: [] } } }) 

testing

 db.Users.insert({name: 'vic', ownedItems: ['one','two']}) // Works db.Users.insert({name: 'ted', ownedItems: ['one']}) // E11000 duplicate key db.Users.insert({name: 'ted', ownedItems: ['two']}) // E11000 duplicate key db.Users.insert({name: 'ted', ownedItems: ['one', 'three']}) // E11000 duplicate key db.Users.insert({name: 'ted', ownedItems: ['three']}) // Works db.Users.insert({name: 'ann', ownedItems: ['four','four']}) // E11000 duplicate key db.Users.insert({name: 'jim', ownedItems: []}) db.Users.insert({name: 'pen', ownedItems: []}) // Works 

如果你需要更复杂的东西,你需要在你的应用中实现逻辑,如果需要的话,包括交易系统。 像Maria / Postgres这样的传统RDBMS可以更好地支持更复杂的数据库逻辑和事务。