Home > Mobile >  problem with mongoose virtual populate (populated field is missing)
problem with mongoose virtual populate (populated field is missing)

Time:10-16

i was using mongoose in my project with typescript when i add virtual called subdomains to populate the data from another collection its working without error but i can't print the populated data directly, i can only access the value using console.log((r as any).subdomains) but when print the console.log(r as any) there is no field called subdomains,please check example 1 and example 2

export interface IDomain{
    domain:string
    owner:Schema.Types.ObjectId,
}

const domainSchema = new Schema<IDomain>({
    domain:{type:String,required:true},
    owner:{type:Schema.Types.ObjectId,required:true},

})
domainSchema.virtual("subdomains",{
    ref:"DomainMonitor",
    localField: '_id',
    foreignField: 'owner'})

Querying the database | example 1

Domain.findOne({owner:"633ebe32d0733c0a8eb4f8d6"}).populate("subdomains").then(r=>{
        console.log(domains)
})

output | example 1

{
  _id: new ObjectId("6342fa2d4b730f004704eb45"),
  domain: 'dummy.com',
  __v: 0,
  owner: new ObjectId("633ebe32d0733c0a8eb4f8d6")
}

Query the database | example 2

Domain.findOne({owner:"633ebe32d0733c0a8eb4f8d6"}).populate("subdomains").then(r=>{
        const domains= (r as any).subdomains
        console.log(domains)
    })

output | example 2

[{
  _id: new ObjectId("6342fa314b730f004704eb47"),
  owner: new ObjectId("6342fa2d4b730f004704eb45"),
  subdomain: [
    'dummy',
  ],
  wildcard: [ '*.dummy.com', '*.dummy.com' ],
  __v: 1
}]

CodePudding user response:

The reason is stated in the mongoose documentation (https://mongoosejs.com/docs/guide.html):

If you use toJSON() or toObject() mongoose will not include virtuals by default. This includes the output of calling JSON.stringify() on a Mongoose document, because JSON.stringify() calls toJSON(). Pass { virtuals: true } to either toObject() or toJSON().

Basically your console.log statement makes a call to toJSON and does not include virtuals by default.

You can include the following in your schema definition in order to include virtuals in your toJSON calls:

domainSchema.set('toJSON', { virtuals: true });

CodePudding user response:

Another approach where you represent your schema as object, not as JSON (using .-operator) is the following:

// create a new schema
const MessageSchema = new mongoose.Schema(
    {
        channel: { type: String },
        content: { type: String, required: true },
        moderator: { type: Number },
    },
    // Add this to your Schema
    {
        toObject: { virtuals: true },
        // alternatively: toJSON: { virtuals: true}, if you want your output as json
    }
);

// Approach 2:
const mySchema = new mongoose.Schema({
  domain: { type:String, required:true },
  owner: { type:Schema.Types.ObjectId, required:true }
});
mySchema.set('toObject', { virtuals: true })

Mongoose Documentation says:

Keep in mind that virtuals are not included in toJSON() and toObject() output by default. If you want populate virtuals to show up when using functions like Express' res.json() function or console.log(), set the virtuals: true option on your schema's toJSON and toObject() options.

  • Related