Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to persist array of objects in mongo using mongoose

I'm trying to persist an array of objects in a document using mongoose. I have tried multiple times but it's not persisting array in document. It places an empty array in document.

Following is my Schema:

var ProfileSchema = new Schema({

  name: String,
  PagesData: [{
    pageAccessToken: {type: String, get: decryptText, set: encryptText},
    category: String,
    name: String,
    id: String,
    perms: [String]
  }]

});

module.exports = mongoose.model('Profile', ProfileSchema);

I'm trying to save a document with an array of objects using following query:

var newProfile = new Profile();
newProfile.name = "someName";
newProfile.PagesData = [ { pageAccessToken: 'someToken',
    category: 'Bags/Luggage',
    name: 'someBrandName',
    id: '12345',
    perms: 
     [ 'ADMINISTER',
       'EDIT_PROFILE',
       'CREATE_CONTENT' ] } ];

newProfile.save(function(err, result, numAffected){
    if(err) {
        console.log(err);
        res.send(500, "Error");
    }
    console.log(result);
    res.send(200, "Success");
});

I tried debugging the mongo commands using

require('mongoose').set('debug', true)

On Debug logs it shows, empty array during insert command execution.

Can anyone please tell me how can I store this array of object in my schema ?

Thanks,

Update:

It's been too long and I'm still not able to figure out the root cause of the problem. There is a long thread going on github for this. https://github.com/Automattic/mongoose/issues/3249 I would like other experts to please take a look and suggest me some way by which I can solve the issue. I'm really stuck at this.

Update 2:

None of the solution worked for me so far, so I decided to modify the schema only to meet my requirements. This resulted in a different problem:

I want to create a map with a objectId as key and an array of string values as its value. The closest that I can get is:

var schema = new Schema({
   map: [{myId: {type:mongoose.Schema.Types.ObjectId, ref: 'MyOtherCollection'}, values: [String]}]
});

But somehow this is not working for me. When I perform an update with {upsert: true}, it is not correctly populating the key: value in the map. In fact, I'm not even sure if I have declared the schema correctly.

Can anyone tell me if the schema is correct ? Also, How can I perform an update with {upsert: true} for this schema?

Also, if above is not correct and can;t be achieved then how can I model my requirement by some other way. My use case is I want to keep a list of values for a given objectId. I don't want any duplicates entries with same key, that's why picked map.

Please suggest if the approach is correct or should this be modelled some other way?

Thanks

like image 405
dark_shadow Avatar asked Aug 10 '15 13:08

dark_shadow


People also ask

What does save () do in mongoose?

save() is a method on a Mongoose document. The save() method is asynchronous, so it returns a promise that you can await on. When you create an instance of a Mongoose model using new, calling save() makes Mongoose insert a new document.

Is Mongoose good for MongoDB?

Mongoose, a neat ODM library for MongoDB used in Node. js projects, has plenty of useful features that make developers' lives easier. It manages relationships between data, has schema validation, and overall allows coding 3-5 times faster.

What is the difference between schema and model in mongoose?

A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.

Does Mongoose create collection automatically?

Here mongoose will check if there is a collection called "Users" exists in MongoDB if it does not exist then it creates it. The reason being, mongoose appends 's' to the model name specified. In this case 'User' and ends up creating a new collection called 'Users'.


3 Answers

I tried the exact code you have provided here and it's working for me. I am not sure what is causing the issue for you. Until and unless we get the same issue, it's very difficult to rectify it. Here are few suggestions which you might try:

  1. Create a simple schema and try storing the object, that way you can figure it out if it has to do something with the schema.
  2. You can try out your schema in a sample app to find if some dependency is causing the problem.

Once you know where exactly the problem is, you would be able to figure out a solution too. I hope it helps.

like image 118
Rudra Avatar answered Sep 19 '22 10:09

Rudra


I tested this and the insert works for me using the below: (I had to remove the get: decryptText, set: encryptText)

var n = { name: "Testing for mongoose", PagesData : [{ pageAccessToken: 'someToken',
    category: 'Bags/Luggage',
    name: 'someBrandName',
    id: '12345',
    perms: 
     [ 'ADMINISTER',
       'EDIT_PROFILE',
       'CREATE_CONTENT' ] } ] }



Profile.create(n, function (err) {
            if (!err) {

                return 'records saved successfully';
            }
            else {

                return error on save:' + err;
            }
        });

Screenshot from DB result:

like image 31
Stacey Burns Avatar answered Sep 19 '22 10:09

Stacey Burns


To create multiple pageDatas you can use it as an embedded collection instead of using arrays.

The Schema will be as follows:

var PagesDataSchema = new Scheme({

    pageAccessToken: {type: String, get: decryptText, set: encryptText},
    category: String,
    name: String,
    id: String,
    perms: [String]
})
var ProfileSchema = new Schema({

  name: String,
  PagesData: [PagesDataSchema]

});

module.exports = mongoose.model('Profile', ProfileSchema);

Reference: http://mongoosejs.com/docs/subdocs.html

For Saving the document you can use like.

exports.save = function(req,res){
var test = new ProfileSchema;  // new object for ProfileSchema domain.
test.name= req.body.name;
if(req.body.PagesData){
 req.body.PagesData.forEach(function(page){  // For every element of pageData from   client.
    test.PagesData.push(page)  // This pushes each and every pagedata given from the client into PagesData.
})
}
test.save(function (saveErr, saved) {  // Saves the new document into db.
if (saveErr) {
    console.log(saveErr)
    return;
}
res.status(HttpStatus.OK).json(saved);
});
};

Hope this helps.

like image 37
SUNDARRAJAN K Avatar answered Sep 20 '22 10:09

SUNDARRAJAN K