如果直接从查询返回文档,则不会调用 mongoose 模式转换
mongoose schema transform not invoked if document is returned directly from query
我有一个端点执行如下操作:
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
字段,但我想将该字段重命名为 id
。 This question addresses this issue, and specifically 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
?
值得一提的是,在我从文档中读取属性的其他地方调用了 toJSON
和 toObject
(console.log
s 显示)。就像我这样做:
const doc = await MyModel.findById('someId');
const name = doc.name;
res.status(200).json(doc);
响应包含 id
而不是 _id
。这几乎就像一旦我对文档进行任何操作都会调用转换函数,但是如果我在文档从数据库到达时直接传递它们,则 toJSON
和 toObject
都不会被调用。
提前感谢您的见解。 :)
toJSON
和 toObject
方法在这里不起作用,因为它们不适用于聚合管道中的文档。 Mongoose 不会将聚合文档转换为 mongoose 文档,它 returns 管道操作返回的原始对象。我最终通过添加管道阶段来实现这一点,首先添加一个与 _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);
我有一个端点执行如下操作:
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
字段,但我想将该字段重命名为 id
。 This question addresses this issue, and specifically 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
?
值得一提的是,在我从文档中读取属性的其他地方调用了 toJSON
和 toObject
(console.log
s 显示)。就像我这样做:
const doc = await MyModel.findById('someId');
const name = doc.name;
res.status(200).json(doc);
响应包含 id
而不是 _id
。这几乎就像一旦我对文档进行任何操作都会调用转换函数,但是如果我在文档从数据库到达时直接传递它们,则 toJSON
和 toObject
都不会被调用。
提前感谢您的见解。 :)
toJSON
和 toObject
方法在这里不起作用,因为它们不适用于聚合管道中的文档。 Mongoose 不会将聚合文档转换为 mongoose 文档,它 returns 管道操作返回的原始对象。我最终通过添加管道阶段来实现这一点,首先添加一个与 _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);