Mongoose 嵌套对象数组中的唯一值
Posted
技术标签:
【中文标题】Mongoose 嵌套对象数组中的唯一值【英文标题】:Mongoose Unique values in nested array of objects 【发布时间】:2013-04-02 01:11:18 【问题描述】:对于我的项目,我想为组织组保留一个 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 声明“唯一:真实”,但这没有用。有没有办法用 mongoose 或 mongoDB 做到这一点而无需额外的查询或拆分架构?
编辑: 我将 uid 的先前值更改为 uid : type : Schema.Types.ObjectId, ref : 'User', index: unique: true, dropDups: true 但这似乎仍然不起作用。
编辑:假设没有简单的方法来实现这一点,我添加了一个额外的查询来检查用户是否已经在组中。这在我看来是最简单的方法。
【问题讨论】:
检查这将是helpful 感谢您的链接。我尝试了以下方法: uid : type : Schema.Types.ObjectId, ref : 'User', index: unique: true, dropDups: true 而不是 uid 的旧值。这仍然不起作用,我也尝试重新启动 mongoDB,但没有成功。 【参考方案1】:数组字段上的唯一索引强制相同的值不能出现在集合中多个文档的数组中,但不会阻止相同的值出现多次单个文档的数组。因此,您需要在向数组添加元素时确保唯一性。
仅当值不存在时,才使用$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
不存在于users
的任何元素的uid
字段中时发生。所以它模仿$addToSet
的行为,但只是uid
。
【讨论】:
但是你怎么能强制只有 uid 是唯一的呢?在 users 数组中,我有更多的属性,每次添加相同的用户(如日期)时可能会有所不同。 感谢您的意见。我已经阅读了有关验证器的信息,但我没有看到比添加额外的查询检查用户是否已经在组中更简单的方法了。 我们如何在第一次创建对象时确保这一点,使用验证或预保存挂钩? 如果添加的用户超过 1 个,这种方法将如何工作?那么对象数组呢?谢谢 这不会在尝试添加具有重复 ID 的用户时引发错误。【参考方案2】:这可能是个老问题,但对于 mongoose > v4.1,您可以使用 $addToSet
运算符。
$addToSet 运算符将一个值添加到数组中,除非该值已经存在,在这种情况下,$addToSet 不会对该数组执行任何操作。
示例:
MyModal.update(
_id: 1 ,
$addToSet: letters: [ "c", "d" ]
)
【讨论】:
我不认为这是一个很好的例子,因为这会将["c", "d"]
的整个数组附加到数组letters
作为一个元素,所以字母将是["a", "b", ["c", "d"]]
参见@987654321 @
除了$addToSet 之外,还可以使用$each 运算符将数组中的所有元素添加到数组中。 $addToSet: letters: $each: [ "c", "d"] 将完成所需的工作。谢谢
非常适合我的需要!以上是关于Mongoose 嵌套对象数组中的唯一值的主要内容,如果未能解决你的问题,请参考以下文章
合并嵌套在数组 mongoose 中的对象内的 $lookup 值
Nodejs mongoose根据对象属性选择嵌套数组中的对象