Mongoose嵌套对象数组中的唯一值

时间:2013-04-10 09:16:17

标签: node.js mongodb mongoose

对于我的项目,我想为组织组保留一份mongoose文档,如下所示:

var groupSchema = Schema({
  name : { type : String },
  org : { type : Schema.Types.ObjectId, ref : 'Organization' },
  ...
  users : [{
    uid : { type : Schema.Types.ObjectId, ref : 'User' },
    ...
  }]
});

我想阻止同一个用户在同一个群组中两次。为此,我需要强制users.uid在users数组中是唯一的。我尝试为uid说明'unique:true',但这不起作用。有没有办法用mongoose或mongoDB执行此操作而无需额外查询或拆分架构?

编辑: 我将uid的先前值更改为     uid:{type:Schema.Types.ObjectId,ref:'User',index:{unique:true,dropDups:true}} 但这似乎仍无效。

编辑:假设没有简单的方法来实现这一点,我添加了一个额外的查询来检查用户是否已经在组中。在我看来,这是最简单的方法。

2 个答案:

答案 0 :(得分:74)

数组字段上的唯一索引强制相同的值不能出现在集合中多个文档的数组中,但不会阻止相同的值出现多次单个文档的数组。因此,您需要确保在向阵列添加元素时的唯一性。

仅当值尚未存在时,才使用$addToSet运算符向数组添加值。

Group.update({name: 'admin'}, {$addToSet: {users: userOid}}, ...

但是,如果users数组包含具有多个属性的对象,并且您希望确保其中一个属性的唯一性(在这种情况下为uid),那么您需要采用另一种方法:

var user = { uid: userOid, ... };
Group.update(
    {name: 'admin', 'users.uid': {$ne: user.uid}}, 
    {$push: {users: user}},
    function(err, numAffected) { ... });

只有在$push的任何元素的user.uid字段中尚不存在uid时才会使users更新符合要求。因此,它模仿$addToSet行为,但仅适用于uid

答案 1 :(得分:3)

这可能是个老问题了,但是对于猫鼬> v4.1,可以使用$addToSet运算符。

  

$ addToSet运算符将一个值添加到数组,除非该值已存在,在这种情况下,$ addToSet对该数组不执行任何操作。

示例:

MyModal.update(
   { _id: 1 },
   { $addToSet: {letters: [ "c", "d" ] } }
)