Search code examples
mongoosemongoose-schemamongoose-populate

Using populate to get reference document, but it is returning the full document in an array of 1


Whenever I call the client, it displays the full json of the client document in client[0]. I want to be able to call work.client.name and work.client.url and such. Sorry if this is a duplicate question, I searched long and hard and never found an answer.

The work controller

exports.work_detail = function(req, res, next) {

    async.parallel({
        work: function(callback) {
            Work.findById(req.params.id)
                .populate('client')
                .exec(callback);
        }
    }, function(err, results) {
        if (err) { return next(err); }
        if (results.work==null) { // No results.
            var err = new Error('Work not found');
            err.status = 404;
            return next(err);
        }
        // Successful, so render.
        console.log(results.work.client.name);
        res.render('work/work_detail', { title: 'Work Details', work:  results.work } );
    });

};

The work model

var workSchema = new Schema({
    client: [{ type: Schema.Types.ObjectId, ref: 'Client', required: true }],
    time: {
        type: Number,
    },
    work_done: {
        type: Array,
    },
    work_value: {
        type: [{}],
    },
    total: {
        type: Number,
        // set: calculateValue
    },
    work_address: {
        type: String,
    },
    note: {
        type: String,
    }
    }, {
    timestamps: true
});

The client model

var clientSchema = new Schema({
    first_name: {
        type: String,
        required: true,
        set: firstToUpper
    },
    last_name: {
        type: String,
        required: true,
        set: firstToUpper
    },
    address: {
        type: String,
        required: false,
    },
    phone: {
        type: Number,
        required: false,
    },
    email: {
        type: String,
        required: false,
        lowercase: true
    },
    note: {
        type: String,
        required: false,
    }}, {
    timestamps: true,
    toObject: { virtuals: true },
    toJSON: { virtuals: true },
});

// Capitalize first letter of each word when called
function firstToUpper (string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

// Virtual for client's full name
clientSchema
.virtual('name')
.get(function () {
    return this.first_name + ' ' + this.last_name;
});
// Virtual for clients's URL
clientSchema
.virtual('url')
.get(function () {
    return '/invoice/client/' + this._id
});

Solution

  • Schema was wrapped in array on accident, pointed out by Neil Lunn