Zane Claes
Zane Claes

Reputation: 14954

Updating Linked Schemas in Mongoose / Mongo & Node.js

I am using Mongo / Mongoose in Node.js to cache data. A Cache object contains a number of CachedPages. In other words:

var PageSchema = {
                'source':                    String,
                'data':                     {}
            };
var PageModel = mongoose.model('pages',PageSchema);

var CacheSchema = {
                'last_updated':             Date,
                'pages':                   [PageSchema]
            }
var CacheModel = mongoose.model('caches',CacheSchema);

When an array of new page data comes in, I cache it by first inserting a new CachedPage for each of the new objects, eg.

var data = new PageModel({'source': page.source, 'data': page.contents});
data.save(function(err){
    // error handling removed
    pages.push(data);
});

Finally, I save the pages into a new Cache:

var cache = new CacheModel({'last_updated': new Date(), 'pages': pages});
cache.save(...);

So far so good! Everything is saved properly.

The problem comes when I want to update a page. When I perform an upsert to modify a PageModel, it does not seem to affect the data in the pages within CacheModel. Eg, if I do:

PageModel.update({'_id': id_to_update}, {'data': new_data}, {'upsert': true}, function(...));

Then, even though the page is updated, when I do a "find" to retrieve the cache, the array of pages still reflects the old data.

It was my understanding that the benefit of using the PageSchema as part of the declaration of the CacheSchema was that the objects would be linked, such that updates to the Pages are reflected within the Cache. What am I missing?

Obviously, I could change the CacheSchema.pages be an array of _ids, and then when I want to retrieve the cache I'll do a 2nd query on the PageModel to convert the array of _ids into an array of objects. This would solve the problem, but it adds a 2nd query...

Thanks!

Upvotes: 0

Views: 1902

Answers (1)

JohnnyHK
JohnnyHK

Reputation: 311895

You're misunderstanding the embedded document concept in Mongoose/Mongo. Embedding your page documents in an array within a cache document creates independent copies of the page documents that just have the same _id values. If you wanted to go with this schema design it would be up to you to make sure any changes made to documents in the pages collection are also made to the embedded pages arrays of the documents in the caches collection.

The more typical choice here would be to, as you mentioned, make CacheSchema.pages an array of _ids, but then use Mongoose's populate support to follow the refs to their full object when needed. So pages would look like this in CacheSchema:

pages: [{ type: Schema.ObjectId, ref: 'pages' }]

Upvotes: 3

Related Questions