Trofee
Trofee

Reputation: 33

MongoDB - Create MongooseDocumentArray from Javascript Array

I'm working with the following schema, I've only shown the relevant parts here:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;
    var punchSchema = new Schema({punch: Date});
/**
 * Child Schema
 */
var ChildSchema = new Schema({
    punchesIn: [punchSchema]
});

mongoose.model('Child', ChildSchema);

And what I am trying to accomplish is to be able to take a Child Document, and update the punchesIn field from a javascript array. So if I had:

Child1{
    _id: XYZ
    punchesIn: [Date1, Date2, Date3]
}

jsArray = [Date4, Date2, Date5]

I would be able to run an update and Child1 would become:

Child1{
    _id: XYZ
    punchesIn: [Date4, Date2, Date5]
}

Here is a dumbed down version of what I attempted, there are no syntax errors with the actual implementation, this is just for show:

Child.findById(XYZ, function(err, child) {
    var query = {'_id': XYZ };
    var update = {  $set: {
                        punchesIn: jsArray
                    },
                 };
    var options = { new: true };
    Child.findOneAndUpdate(query, update, options, function(err, child) {
        if (err) {
            console.log('got an error');
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        }
    });

Running this code, which I know works for non array fields in a document, results in the following error:

500 TypeError: Cannot use 'in' operator to search for '_id' in punchesIn

From what I can gather, this is because punchesIn is of the type MongooseDocumentArray, and jsArray is just a a javascript array.

Would it be possible to run some kind of loop that would create a MongooseDocumentArray where the different fields are document versions of the Dates found in the jsArray?

Upvotes: 0

Views: 115

Answers (1)

mr.freeze
mr.freeze

Reputation: 14050

You'll need to convert your javascript array to an array of Punch model instances since that's what the Child schema expects. Here's a function that does it:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var punchSchema = new Schema({punch: Date});

var childSchema = new Schema({
    punchesIn: [punchSchema]
});

var Child = mongoose.model('Child', childSchema);
var Punch = mongoose.model('Punch', punchSchema);

function createPunchList(inArr){
    var outArr = [];
    for (var i=0;i<inArr.length;i++){
        var punch = new Punch({
           date: inArr[i]
        });
        outArr.push(punch);
    }
    return outArr;
}

//test data
for (var i=0;i<10;i++){
    var newChild = new Child({
       punchesIn: createPunchList([new Date(), new Date(), new Date()])
    });

    newChild.save();
}

Child.find({}, function(err, c){
    console.log(c);
});

Upvotes: 1

Related Questions