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

Node.js Mongoose对象嵌套数组中的唯一值,node.js,mongodb,mongoose,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' }, ... }] }); 我

对于我的项目,我想为组织团体保留一个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',索引:{unique:true,dropDups:true} 但这似乎仍然不起作用


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

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

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

Group.update({name: 'admin'}, {$addToSet: {users: userOid}}, ...
但是,如果用户数组包含具有多个属性的对象,并且在这种情况下,您希望确保其中一个属性的唯一性,则需要采取另一种方法:

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

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

这可能是个老问题,但对于mongoose>v4.1,您可以使用$addToSet操作符

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

例如:

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

检查此链接将非常感谢您的链接。我尝试了以下方法:uid:{type:Schema.Types.ObjectId,ref:'User',index:{unique:true,dropDups:true}}而不是uid的旧值。这仍然不起作用,我也尝试重新启动mongoDB,但没有成功。但是如何强制唯一uid是唯一的呢?在用户数组中,我有更多的属性,每次添加相同的类似用户的日期时,这些属性可能会有所不同。感谢您的输入。我已经读过关于验证器的内容,但没有比添加额外的查询检查用户是否已在组中更简单的方法了。@GuidoPassage我添加了一种方法来支持您的特定用例。我们如何在第一次创建对象时确保这一点,使用验证或预保存挂钩?如果添加的用户超过1个,该方法将如何工作?那么一组对象?ThanksI不认为这是一个好例子,因为这会将[c,d]的整个数组作为一个元素附加到数组字母中,因此字母将是[a,b,[c,d]]请参见$addToSet之外的每个运算符都可以用于将数组中的所有元素添加到数组中。{$addToSet:{字母:{$each:[c,d]}}}}将完成所需的工作。谢谢