6

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

SUNDARRAJAN K
  • 2,237
  • 2
  • 22
  • 38
dark_shadow
  • 3,503
  • 11
  • 56
  • 81
  • You might want to make Update 2 a different question, since it's quite different. – phillee Aug 17 '15 at 04:27
  • By an {upsert:true} update, do you mean inserting an element into map, and replacing it if myId already exists? Have you considered creating a separate collection for it altogether, instead of embedding them into map? – phillee Aug 17 '15 at 04:29
  • @phillee: I have created a separate post for Update 2 http://stackoverflow.com/questions/32038606/defining-a-map-with-objectid-key-and-array-of-strings-as-value-in-mongoose-schem – dark_shadow Aug 17 '15 at 07:05
  • @phillee: Yes, if there is already an entry for a given myId, another insert should update the previous one. I think making a separate collection is not correct way as based on db design, I think there should be some map for a given objectId and corresponding values as array of string – dark_shadow Aug 17 '15 at 07:08

4 Answers4

8

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.

Rudra
  • 1,678
  • 16
  • 29
5

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:

Stacey Burns
  • 1,092
  • 7
  • 14
  • Can you please take a look at the github discussion. You can see there has been changes in the query. I'm using update query now. Also, I have written a detailed problem over there. It'll be helpful to give you an exact problem where I'm stuck – dark_shadow Aug 13 '15 at 15:13
  • 1
    Ok I'll have a look but it's a bit confusing to have two discussions going on in two different forums – Stacey Burns Aug 13 '15 at 15:45
  • I agree, infact earlier I was thinking of posting it only on github but since to reach a wider audience, I decided to create a thread over here as well. Also, I will definitely try to keep both of these in sync. – dark_shadow Aug 13 '15 at 15:51
  • Ok you have a field called type in the other post. I think mongoose gets confused with this. Try changing the field to login_type or something like this. – Stacey Burns Aug 13 '15 at 16:38
  • I tried changing that but still not able to fix the issue. Also, please take a look at https://github.com/Automattic/mongoose/issues/3249#issuecomment-130773731 Do you think this can be a possible issue ? – dark_shadow Aug 13 '15 at 17:59
  • what is newSocialProfile? You don't show where you set it? – Stacey Burns Aug 13 '15 at 18:20
  • Its newProfile only, updated my comment over there as well. – dark_shadow Aug 13 '15 at 18:21
  • The code that vkarpov15 gave you before your last post, did you try using it? If not, what is different between the two? – Stacey Burns Aug 13 '15 at 19:29
  • I have tried that but the issue is somehow that works only as a standalone script. If I do same thing in my app, it doesn't work – dark_shadow Aug 14 '15 at 01:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/86961/discussion-between-stacey-burns-and-dark-shadow). – Stacey Burns Aug 14 '15 at 07:33
  • I have changed my schema and now landed in another problem. Please take a look at my update in the question and let me know your thoughts on that – dark_shadow Aug 17 '15 at 03:59
3

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.

SUNDARRAJAN K
  • 2,237
  • 2
  • 22
  • 38
0

Have you tried

Profile.create({
  name: "someName",
  PagesData: [
    {
      pageAccessToken: 'someToken',
      category: 'Bags/Luggage',
      name: 'someBrandName',
      id: '12345',
      perms: [
        'ADMINISTER',
        'EDIT_PROFILE',
        'CREATE_CONTENT'
      ]
    }
  ]
}, function(err, profile) {
    // do your stuff
})

?

Patosai
  • 750
  • 1
  • 6
  • 16