【问题标题】:mongoose virtual property not working in findById propertymongoose 虚拟属性在 findById 属性中不起作用
【发布时间】:2021-04-29 19:39:09
【问题描述】:

我有一个serviceSchema,如下所示:

const serviceSchema = new mongoose.Schema(
  {
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User",
      required: true,
    },
    title: {
      type: String,
      required: true,
    },
    description: {
      type: String,
      required: true,
    },
    tags: [
      {
        type: String,
        required: true,
      },
    ],
    image: {
      type: String,
      required: true,
      get: (rawImage) => {
        return `${config.base_url}/uploads/${rawImage}`;
      },
    },
  },
  {
    timestamps: true,
    toJSON: { getters: true, virtuals: true },
  }
);

我已经定义了一个这样的虚拟:

serviceSchema.virtual("avg_satis").get(function () {
  Session.find({ service: this._id, status: "conf" }, "satisfaction")
    .lean()
    .then((sessions) => {
      let sum = 0;
      sessions.forEach((session) => {
        sum += session.satisfaction;
      });
      console.log(sum / sessions.length);
      return sum / sessions.length;
    })
    .catch((err) => console.log(err));
});

当我执行这样的查询时:

      const service = await Service.findById(req.params.service_id).populate(
        "user",
        "_id name pp"
      );
      console.log(service.avg_satisf);

虚拟未定义。

我也尝试像这样转换虚拟(没有承诺):

serviceSchema.virtual("avg_satis").get(function () {
  Session.find({ service: this._id, status: "conf" }, "satisfaction")
    .lean()
    .exec((err, sessions) => {
      if (err) {
        console.log(err);
      }
      let sum = 0;
      sessions.forEach((session) => {
        sum += session.satisfaction;
      });
      console.log(sum / sessions.length);
      return sum / sessions.length;
    });
});

【问题讨论】:

  • virtual 不允许异步功能。
  • @hoangdv 我该如何解决这个问题?
  • 将会话模式添加到问题

标签: javascript node.js mongoose


【解决方案1】:

虚拟字段在数据库中不存在。它是一种速记,所以你不能查询它。 你要的是打电话populate,请阅读文档并使用它。

如果你真的想在虚拟中得到一个承诺

serviceSchema.virtual("avg_satis").get(function () {
  // return promise to caller
  return Session.find({ service: this._id, status: "conf" }, "satisfaction")
    .lean()
    .then((sessions) => {
      let sum = 0;
      sessions.forEach((session) => {
        sum += session.satisfaction;
      });
      console.log(sum / sessions.length);
      return sum / sessions.length;
    })
    .catch((err) => console.log(err));
});


// outside
await service.avg

在文档中还有另一种方式,例如静态或方法

----更新

它已经在猫鼬文档中

  // define a schema
  const animalSchema = new Schema({ name: String, type: String });

  // assign a function to the "methods" object of our animalSchema
  animalSchema.methods.findSimilarTypes = function(cb) {
    return mongoose.model('Animal').find({ type: this.type }, cb);
  };

所以

  // define a schema
  serviceSchema.methods.caleAvg = async function() {
    return Session.find({ service: this._id, status: "conf" }, "satisfaction")
    .lean()
    .then((sessions) => {
      let sum = 0;
      sessions.forEach((session) => {
        sum += session.satisfaction;
      });
      console.log(sum / sessions.length);
      return sum / sessions.length;
    }).catch((err) => console.log(err));
  };

// outside caller
const avg = await service.caleAvg()

如果你想这样做并附加到它在 mongooDB 中的响应中,你需要研究他们的aggregate 管道。

【讨论】:

  • 你能详细说明一下吗
  • 不,我的意思是用有关架构的更多详细信息更新您的问题
  • 而你在 virtual getter 中什么也没返回,你真正想要做什么?
  • 我确实返回了一些东西:return sum / sessions.length;
  • 但它是在一个承诺中,return Sesstion.... in getter
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多