Mongoose预挂钩中的循环引用问题

问题描述 投票:0回答:1

在我的MongoDB / Node后端环境中,我使用Mongoose prepost钩子中间件来检查文档上的更改,以便创建一些系统注释。

我遇到的一个问题是,当我尝试查找相关文档的记录时,我得到一个"Customer.findOne()" is not a function错误。当我从同一个集合中查找记录时,这只是一个问题,模型刚刚启动了这个prepost钩子触发器文件。换句话说,如果我的“客户”模型在外部文件中的预挂钩函数中启动函数,那么如果我尝试使用标准Customer查找findOne(),则会出现错误:

我的客户模型看起来像这样:

module.exports = mongoose.model(
  "Customer",
  mongoose
    .Schema(
      {
        __v: {
          type: Number,
          select: false
        },
        deleted: {
          type: Boolean,
          default: false
        },
        // Other props
        searchResults: [
          {
            matchKey: String,
            matchValue: String
          }
        ]
      },
      {
        timestamps: true
      }
    )
    .pre("save", function(next) {
      const doc = this;
      trigger.preSave(doc);
      next();
    })
    .post("save", function(doc) {
      trigger.postSave(doc);
    })
    .post("update", function(doc) {
      trigger.postSave(doc);
    })
    .post("findOneAndUpdate", function(doc) {
      trigger.postSave(doc);
    })
);

...从模型调用的findOne()文件中有问题的triggers函数如下所示:

const Customer = require("../../models/customer");

exports.preSave = async function(doc) {
   this.preSaveDoc = await Customer.findOne({
     _id: doc._id
   }).exec();
};

为了澄清,如果我使用findOne()在同一个triggers文件中查找来自不同集合的记录,这不是问题。然后它工作正常。找到Contact时见下文 - 这里没问题:

const Contact = require("../../models/contact");

exports.preSave = async function(doc) {
   this.preSaveDoc = await Contact.findOne({
     _id: doc._id
   }).exec();
};

我发现的解决方法是使用Mongo而不是Mongoose,如下所示:

exports.preSave = async function(doc) {
  let MongoClient = await require("../../config/database")();
  let db = MongoClient.connection.db;

  db.collection("customers")
    .findOne({ _id: doc._id })
    .then(doc => {
      this.preSaveDoc = doc;
    });
}

...但我更喜欢在这里使用Mongoose语法。如何在与查找类型相同的模型/集合中调用的预挂钩函数中使用findOne()

mongodb mongoose middleware
1个回答
1
投票

我前几天遇到过类似的问题。实际上它是一个循环依赖问题。当您在客户模型上调用.findOne()时,它不存在,因为它尚未导出。你应该尝试这样的事情:

const customerSchema = mongoose.Schema(...);

customerSchema.pre("save", async function(next) {
  const customer = await Customer.findOne({
    _id: this._id
  }).exec();
  trigger.setPreSaveDoc(customer);
  next();
})

const Customer = mongoose.model("Customer", customerSchema)

module.export Customer;

这里将定义客户,因为它在创建之前未被调用(预挂钩)。

作为一种更简单的方法(我不确定),但您可以尝试在保存功能导出下的触发器文件中移动联系人导入。这样我觉得这些优点可能有效。

它有帮助吗?

© www.soinside.com 2019 - 2024. All rights reserved.