使用$ push时如何验证数组长度?

时间:2018-08-28 18:15:24

标签: node.js mongodb mongoose

我试图限制用户可以添加到我的一个模式的数组字段中的元素数量。我目前正在使用Schema.findOneAndUpdate();$push运算符将元素添加到数组中。

我尝试的第一件事是在StackOverflow上另一个答案给出的解决方案,即:https://stackoverflow.com/a/29418656/6502807 此解决方案将验证函数添加到架构定义中的字段。通过将runValidators设置为true,我确实获得了与Schema.findOneAndUpdate()一起运行的功能。但是,正是在那一刻,我偶然发现了下一个问题。在猫鼬文档的“验证”一章的末尾,它说:

  

此外,$ push,$ addToSet,$ pull和$ pullAll验证不会在数组本身上运行任何验证,只能在数组的各个元素上运行。

因此,使用$pull时尝试检查数组长度不起作用。它只是每次向验证函数提供一个空数组,而不管其在数据库中的实际内容如何。

我接下来尝试使用的是pre钩子。这也没有任何成功。由于某些原因,即使runValidators设置为true,它也没有执行该挂钩。这就是我定义的钩子的方式:

Settings.pre('update', async function (next) {
    if (this.messages.length > MAX_MESSAGES) {
        throw new Error('Too many messages');
    } else {
        next();
    }
});

编辑:之所以没有触发该函数,是因为我使用的是findOneAndUpdate而不是update,因此此问题已修复,现在可以运行该函数。但是,上面的解决方案代码不起作用。

具有数组的模式如下:

const Settings = new mongoose.Schema({
    // A lot more fields not relevant to this question
    messages: {
        type: [{
            type: String
        }]
    }
});

值得一提的另一件事是,这些更新语句与其他选项结合使用。我需要update语句表现得像更新或插入,以便我完整的选项集看起来像这样:

{
    runValidators: true,
    setDefaultsOnInsert: true,
    upsert: true,
    new: true
}

使用这样的预钩子集执行查询时,可以超出数组限制,而不会引发任何验证错误。

在这一点上,我想知道是否有任何明智的方法来进行这样的最大长度检查,而不必自己在猫鼬的抽象层之外进行。

我正在将Mongoose 5.2.6与MongoDB 4.0.0一起在节点v9.11.1上运行。

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

如果您使用的是mongodb和mongoose的最新版本,则可以使用$expr运算符

<?php
      if(preg_match($pattern,$sentence)); /** Sentece can be a list like $sentence[0]*/
      $count++; 
?>
the word.

答案 1 :(得分:0)

您应该可以使用pre update钩子来做到这一点。问题是,默认情况下,该钩子不会give来指示您是要进行更新的管理员,因此您可以进行验证。必须通过take itthis.getUpdate()

Settings.pre('update', async function (next) {
    var preUpdate = this.getUpdate()
    // now inside of the preUpdate you would have your update being made and should have the array in there on which you can check the length
});

要在测试模式中给您一个想法,我必须在具有 $ set 的更新中执行以下操作:

this.getUpdate().$set.books.length   // gave me 2 which was correct etc

我也没有问题,也没有碰到update钩子。在猫鼬文档中看起来超级简单:

AuthorSchema.pre('update', function(next) {
  console.log('UPDATE hook fired!')
  console.log(this.getUpdate())
  next();
});