猫鼬预钩中的循环参考问题

时间:2019-03-06 20:52:05

标签: mongodb mongoose middleware

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

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

我的客户模型如下:

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()

1 个答案:

答案 0 :(得分: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;

将在此处定义客户,因为在创建客户之前不会将其调用(预钩子)。

作为一种更简单的方法(我不确定),但是您可以尝试将联系人导入移动到保存功能导出下的触发器文件中。这样,我认为这种礼节可能有用。

有帮助吗?