5

In the below user schema there is a foobar.events field, that I am trying to push new hashes (that are received from an API POST request) to.

var userSchema = mongoose.Schema({

    foobar: {
        id           : String,
        token        : String,
        email        : String,
        name         : String,
        events       : [{
            action          : String,
            timestamp       : Date,
            user_xid        : String,
            type            : {type: String},
            event_xid       : String    
        }]
    }

});

And here is the logic for that Express route:

app.post('/foobar/post', function(req, res) {
    var jb_user_xid  = req.body['events'][0]['user_xid'];
    var jb_timestamp = req.body['events'][0]['timestamp'];
    var jb_action    = req.body['events'][0]['action'];
    var jb_type      = req.body['events'][0]['type'];
    var jb_event_xid = req.body['events'][0]['event_xid'];

    User.findOne({'foobar.id':jb_user_xid}, function(err, user) {
        console.log(user);
        user.foobar.events.push({
            user_xid: jb_user_xid,
            timestamp: jb_timestamp,
            action: jb_action,
            type: jb_type,
            event_xid: jb_event_xid
        });
        user.save(function(err) {
            if (err){ 
                console.log("Error on save: " + err);
            }
            else {
                console.log("Save successful");
            }
        });
    });

    res.writeHead(200);
    res.end();
    return;
});

The find method is executed successfully, but the following error is thrown when trying to save to the database: Error on save: TypeError: Object.keys called on non-object - any idea why this error is being thrown?

This thread had a similar problem, but changing the findOne to findById broke my user query.

As a side note, this is what is returned in req.body from the API:

{  events:
    [ { action: 'updation',
        timestamp: 1408846680,
        user_xid: 'aguxwNqb_Xg87buMyP6Wiw',
        type: 'move',
        event_xid: 'vhAkgg1XwQvLynAkkCc8Iw' } ],
   notification_timestamp: 1408846680 }

And here is what's returned from the User.findOne method

{ __v: 17,
   _id: 53f7d23e432de20200970c10,
   foobar:
    { id: 'aguxwNqb_Xg87buMyP6Wiw',
      name: 'Test User',
      token: 'W3AjaI7_iOWilcKRpmxenQWi',
      events: [] }
}
4
  • How did findById break the user query? The error looks like the user variable's value does not have the correct type. What does user look like when it is logged? Commented Aug 28, 2014 at 17:10
  • The user_xid field links to a specific user, that's why the findOne method is used. I've updated the question to include the user log Commented Aug 28, 2014 at 17:34
  • It could be a problem with your schema. The line that says type: {type: String} should probably be something like event_type: String. I'm not sure if that has anything to do with the issue, it just looks odd to me. Commented Sep 2, 2014 at 21:59
  • @ctlacko The API response includes a field named type, which is a reserved named in Mongoose. Thus, I have to manually override the type with that syntax Commented Sep 3, 2014 at 1:57

2 Answers 2

5

This error was actually due to old data within my Mongo database. The events field was full of extra strings. I deleted these and my original code began working successfully. No changes to the above code were necessary.

Sign up to request clarification or add additional context in comments.

1 Comment

I had this same error and it was because I had a field defined as a custom subschema of Object Ids, but data in this field already contained arrays of strings (that looked like Object Ids). Queries were written to look for strings so they continued to work. Updates would not because Mongo could not run Object.keys() on this subschema that was in fact an array of strings. Lesson: Make sure your schema matches your existing data!
1

I tried your code and it works perfectly.. for me.. try to check mongoose module version or something.if u have still problem please do it using update function rather than save..It would be more performance oriented.

this is the following i used

    var mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/test');
    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'connection error:'));
    db.once('open', function callback () {
      // yay!
    });
    var userSchema = mongoose.Schema({

        foobar: {
            id           : String,
            name         : String,
            events       : [{
                action          : String,
                timestamp       : Date,
                user_xid        : String,
                type            : {type: String},
                event_xid       : String    
            }]
        }

    });







    var User =  mongoose.model('user', userSchema);

    /*
    //used for saving.
    var person =  new User({  foobar:
        { id: 'aguxwNqb_Xg87buMyP6Wiw',
          name: 'Test User',
          token: 'W3AjaI7_iOWilcKRpmxenQWi',
          events: [] }
    });
    person.save(function(err,data){
    console.log(err);
    console.log(data);
    })

    */


    User.findOne({'foobar.id':'aguxwNqb_Xg87buMyP6Wiw'}, function(err, user) {
            console.log(user);
            user.foobar.events.push({ action: 'updation',
            timestamp : 1408846680,
            user_xid: 'aguxwNqb_Xg87buMyP6Wiw',
            type: 'move',
            event_xid: 'vhAkgg1XwQvLynAkkCc8Iw' });
            user.save(function(err) {
                if (err){ 
                    console.log("Error on save: " + err);
                }
                else {
                    console.log("Save successful");
                }
            });
        });

1 Comment

Thank you for looking into this! I will heed your warning for using update rather than save

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.