52

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

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 声明“唯一:真”,但这没有用。有没有办法用 mongoose 或 mongoDB 做到这一点而无需额外的查询或拆分模式?

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

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

4

2 回答 2

133

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

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

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

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

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

这样做是限定$push更新仅在user.uid不存在于uid任何元素的字段中时发生users。所以它模仿$addToSet行为,但只是为了uid.

于 2013-04-10T12:36:11.650 回答
10

好吧,这可能是个老问题,但是对于 mongoose > v4.1,您可以使用$addToSet运算符。

$addToSet 运算符向数组添加一个值,除非该值已经存在,在这种情况下 $addToSet 对该数组不做任何事情。

例子:

MyModal.update(
   { _id: 1 },
   { $addToSet: {letters: [ "c", "d" ] } }
)
于 2018-09-20T20:12:57.353 回答