Циркулярная ссылка в мангусте - PullRequest
0 голосов
/ 06 марта 2019

В моей бэкэнд-среде MongoDB / Node я использую промежуточное ПО Mongoose pre и post для проверки изменений в документе, чтобы в результате создать некоторые системные заметки.

Одна проблема, с которой я сталкиваюсь, заключается в том, что, когда я пытаюсь найти запись для рассматриваемого документа, я получаю ошибку "Customer.findOne()" is not a function. Это ТОЛЬКО проблема, когда я ищу запись из той же коллекции, из которой модель только что запустила этот файл триггеров хуков pre и post. Другими словами, если моя модель «Клиент» запускает функции в функции предварительного подключения во внешнем файле, то я получаю ошибку, если затем пытаюсь найти 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() в функции предварительного подключения, вызываемой из той же модели / коллекции, что и тип поиска?

1 Ответ

1 голос
/ 07 марта 2019

Я столкнулся с подобной проблемой несколько дней назад. По сути, это проблема круговой зависимости. Когда вы вызываете .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;

Здесь клиент будет определен, потому что он не вызывается (предварительный хук) перед его созданием.

Как более простой способ (я не уверен в этом), но вы можете попробовать перенести импорт контактов в свой файл Trigger в экспорт функции сохранения. Таким образом, я думаю, что приличия могут работать.

Помогло ли это?

...