Why does mongoose populate virtual field as array instead of single item?
Asked Answered
R

3

7

I want to populate an object into a virtual field with mongoose as a JSON object, but it always returns an array with a single item.

Here is my scheme code (part with virtual field):

Order.virtual('client', {
    type: 'ObjectId',
    ref: 'User',
    localField: 'clientId',
    foreignField: '_id'
});

Here is how I do population:

Order.findOneAndUpdate({ internalStatus: 2}, { internalStatus: 3 })
    .lean()
    .populate({ path: 'client', select: 'email' })
    .exec(function (err, order) {
        //...
    });

Here is what I receive in returned JSON:

{ _id: 5ad903d90443fe13b8c9061a,
    client: [ { _id: 5b3755fe69635d1e942d00a8, email: '[email protected]' } ] }

This is what I want to achieve:

{ _id: 5ad903d90443fe13b8c9061a,
    client: { _id: 5b3755fe69635d1e942d00a8, email: '[email protected]' } }

Thank you for any help or suggestions!

Raddle answered 16/9, 2018 at 11:9 Comment(0)
T
17

You have to add "justOne : true" to your virtual field config :

Order.virtual('client', {
    type: 'ObjectId',
    ref: 'User',
    localField: 'clientId',
    foreignField: '_id',
    justOne : true

});
Tamelatameless answered 8/4, 2019 at 22:52 Comment(1)
Yes!! it works in Mongoose6.1.4 as wellResonate
S
0

In mongoose [email protected] I am seeing they return as JSON_OBJECT but when I upgraded to [email protected] , it started retuning as JSON_ARRAY

Spinster answered 1/10, 2018 at 12:42 Comment(0)
H
0

Description

  • App(1) = Namescpace(N)
  • App Accessor/virtual field (namespace)
  • Namespace Accessor/virtual field (app)

1. APP

1.1. App model

import { Schema, model, Document, Types } from 'mongoose';
import { INamespace } from './namespace.model';

enum IsActiveEnum {
    Inactive = 0,
    Active = 1,
}

// Define the authentication interface
interface IAuthentication {
    salt: string;
    password: string;
}

interface IApp extends Document {
    name: string;
    authentication: IAuthentication;
    is_active: IsActiveEnum;
    created_by?: number;
    created_at?: Date;
}

const AppSchema = new Schema<IApp>({
    name: { type: String, required: true, unique: true },
    authentication: {
        password: { type: String, required: true, select: false },
        salt: { type: String, required: true, select: false },
    },
    is_active: {
        type: Number,
        enum: [IsActiveEnum.Inactive, IsActiveEnum.Active],
        default: IsActiveEnum.Active,
    },
    created_by: { type: String },
    created_at: { type: Date },
});

// Add a virtual property to the AppSchema
AppSchema.virtual('namespace', {
    type: 'ObjectId',
    ref: 'Namespace',
    localField: '_id',
    foreignField: 'app_id',
});


const AppModel = model<IApp>('AppModel', AppSchema, 'app');

export { IApp, AppModel };

1.2. App Service

const getAppsPaginated = async (req: Request): Promise<any> => {
    let data = await AppModel.find()
        .lean()
        .populate('namespace') // Use the virtual property 'namespaces'
        .exec();

    return data;
};

2. Namespace

2.1. Namespace model

import { Schema, model, Document, Types } from 'mongoose';

enum IsActiveEnum {
    Inactive = 0,
    Active = 1,
}

interface INamespace extends Document {
    name: string;
    path: string;
    is_active: IsActiveEnum;
    created_by?: number;
    created_at?: Date;
    app_id?: Types.ObjectId;
}

const NamespaceSchema = new Schema<INamespace>({
    name: { type: String, required: true, unique: true },
    path: { type: String, required: true, unique: true },
    is_active: {
        type: Number,
        enum: [IsActiveEnum.Inactive, IsActiveEnum.Active],
        default: IsActiveEnum.Active,
    },
    created_by: { type: String },
    created_at: { type: Date },
    app_id: { type: Schema.Types.ObjectId, ref: 'AppModel' }, // Reference to App model
});

// Add a virtual property to the AppSchema
NamespaceSchema.virtual('app', {
    type: 'ObjectId',
    ref: 'AppModel',
    foreignField: '_id',
    localField: 'app_id',
    justOne : true
});


const Namespace = model<INamespace>('Namespace', NamespaceSchema, 'namespace');

export { INamespace, Namespace };

2.2. Namespace Service

const getNamespacePaginated = async (req: Request): Promise<any> => {
    return await Namespace.find()
        .lean()
        .populate('app') // Assuming 'posts' is the name of the field in the User schema referencing the Post model
        .exec();
};
Hospitalization answered 17/1 at 8:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.