I have a mongoose schema as follow
const mongoose = require("mongoose");
const PostSchema = new mongoose.Schema(
{
title:{
type:String,
required: true,
trim: true
},
author:{
type: mongoose.Schema.Types.ObjectId,
ref:'Customer'
},
images: [
{img :{type:String}}
]
},
{ timestamps: true }
);
PostSchema.virtual("images.imgCrop").get(function () {
return `${this.img}/crop/720/720`;
});
module.exports = mongoose.model("Post", PostSchema);
Data result is
[
{
"_id": "64cb808d95a1ec6708a8e5e6",
"title": "First Post",
"images": [],
"createdAt": "2023-08-03T10:33:31.253Z",
"updatedAt": "2023-08-03T10:33:31.253Z",
"__v": 0
},
{
"_id": "64cb829a95a1ec6708a8f9ab",
"title": "Next Post",
"images": [
{
"_id": "64cb829a95a1ec6708a8f9ac",
"img": "image001.png"
},
{
"_id": "64cb829a95a1ec6708a8f9ad",
"img": "image002.png"
},
{
"_id": "64cb829a95a1ec6708a8f9ae",
"img": "image003.png"
}
],
"createdAt": "2023-08-03T10:34:02.173Z",
"updatedAt": "2023-08-03T10:34:02.173Z",
"__v": 0
}
]
In the database I already have a bunch of data, So I need to modify new image path in the return query as imgCrop : "image003.png/crop/720/720"
Is it possible to achive this using mongoose virtual ?
Data is fetch as below
let posts = await Post.find({}).lean().populate('author')
So that the result should become as following
[
{
"_id": "64cb808d95a1ec6708a8e5e6",
"title": "First Post",
"images": [],
"createdAt": "2023-08-03T10:33:31.253Z",
"updatedAt": "2023-08-03T10:33:31.253Z",
"__v": 0
},
{
"_id": "64cb829a95a1ec6708a8f9ab",
"title": "Next Post",
"images": [
{
"_id": "64cb829a95a1ec6708a8f9ac",
"img": "image001.png",
"imgCrop": "image001.png/crop/720/720"
},
{
"_id": "64cb829a95a1ec6708a8f9ad",
"img": "image002.png",
"imgCrop": "image002.png/crop/720/720"
},
{
"_id": "64cb829a95a1ec6708a8f9ae",
"img": "image003.png",
"imgCrop": "image001.png/crop/720/720"
}
],
"createdAt": "2023-08-03T10:34:02.173Z",
"updatedAt": "2023-08-03T10:34:02.173Z",
"__v": 0
}
]
You need to extract ImageSchema
and declare a virtual on it.
const ImageSchema = new mongoose.Schema({
img: { type:String }
});
ImageSchema.virtual('imgCrop').get(function() {
return `${this.img}/crop/720/720`;
});
const PostSchema = new mongoose.Schema(
{
title:{
type: String,
required: true,
trim: true
}
images: [ImageSchema]
},
{ timestamps: true }
);
Mind that the virtuals are not called when using lean()
query.
So you either need to drop lean()
or install and use mongoose-lean-virtuals
plugin:
const mongooseLeanVirtuals = require('mongoose-lean-virtuals');
PostSchema.plugin(mongooseLeanVirtuals);
// Maybe also add this? ImageSchema.plugin(mongooseLeanVirtuals);
Post.find({}).lean({ virtuals: true }).populate('author')