mongodb 如果直接从查询返回文档,则不调用mongoose架构转换

inb24sb2  于 2023-01-12  发布在  Go
关注(0)|答案(2)|浏览(109)

我有一个端点执行如下操作:

const pipeline = [
          {
            $match: {
              $and: [
                {
                  $or: [...],
                },
              ],
            },
          },
          {
            $group: {
              _id : '$someProp',
              anotherProp: { $push: '$$ROOT' },
            },
          },
          { $sort: { date: -1 } },
          { $limit: 10 },
        ]
        const groupedDocs = await MyModel.aggregate(pipeline);

这里的想法是返回的文档看起来像这样:

[
  {
    _id: 'some value',
    anotherProp: [ /* ... array of documents where "someProp" === "some value" */ ],
  },
  {
    _id: 'another value',
    anotherProp: [ /* ... array of documents where "someProp" === "another value" */ ],
  },
  ...
]

在得到这些结果之后,端点用一个包含anotherProp的所有成员的数组来响应,如下所示:

const response = groupedDocs.reduce((docs, group) => docs.concat(group.anotherProp), []);
res.status(200).json(response);

我的问题是响应中的最终文档包含_id字段,但我想将该字段重命名为idThis question解决了这个问题,特别是this answer是 * 应该 * 工作的,但由于某种原因转换函数没有被调用。

schema.set('toJSON', {
    virtuals: true,
    transform: function (doc, ret) {
        console.log(`transforming toJSON for document ${doc._id}`);
        delete ret._id;
    },
});
schema.set('toObject', {
    virtuals: true,
    transform: function (doc, ret) {
        console.log(`transforming toObject for document ${doc._id}`);
        delete ret._id;
    },
});

但是console.log语句没有被执行,这意味着转换函数没有被调用,所以我仍然在响应中得到_id而不是id
因此,我的问题是在此场景中如何获得id而不是_id
值得一提的是,toJSONtoObject在我从文档读取属性的其他地方被调用(console.log s显示)。

const doc = await MyModel.findById('someId');
const name = doc.name;
res.status(200).json(doc);

响应包含id而不是_id,这几乎就像我对文档执行任何操作时都会调用transform函数一样,但是如果在文档从数据库到达时直接传递文档,则toJSONtoObject都不会被调用。
提前感谢你的见解。:)

mcdcgff0

mcdcgff01#

toJSONtoObject方法在这里不起作用,因为它们不适用于来自聚合管道的文档。Mongoose不会将聚合文档转换为mongoose文档,它返回管道操作返回的原始对象。我最终通过添加管道阶段来实现这一点,首先添加一个id字段,该字段的值与_id字段的值相同。然后第二步删除_id字段。所以我的流水线基本上变成了:

const pipeline = [
          {
            $match: {
              $and: [
                {
                  $or: [...],
                },
              ],
            },
          },
          // change the "_id" to "id"
          { $addFields: { id: '$_id' } },
          { $unset: ['_id'] },
          {
            $group: {
              _id : '$someProp',
              anotherProp: { $push: '$$ROOT' },
            },
          },
          { $sort: { date: -1 } },
          { $limit: 10 },
        ]
        const groupedDocs = await MyModel.aggregate(pipeline);
s5a0g9ez

s5a0g9ez2#

从聚合中获取原始对象后,可以将其重新转换为mongoose文档,只需将它们逐个转换回来,它们将在返回时触发toJSON

const document = Model.hydrate(rawObject);

答案在这里找到:Cast plain object to mongoose document

相关问题