Michael
Michael

Reputation: 42050

How to manage drafts and multiple versions in Mongo?

This is a follow-up to my previous question.

Suppose there is a product catalog stored as a collection in Mongo. User Alice is a catalog manager and may update, remove and add products to the catalog. User Bob is a customer and may view the catalog.

Currently when Alice changes the catalog Bob sees the changes immediately. Now we want the changes to be visible only if Alice explicitly publish them. For example:

  1. There is a catalog which consists of Product A, Product B, and Product C. Both Alice and Bob see the same products.

  2. Alice changed the catalog. She modified Product A, removed Product C, and added Product D but did not publish the changes.

    Now Alice sees Product A' (modified), Product B, and Product D but Bob still sees the previous version: Product A, Product B, and Product C.

  3. Alice published the catalog. Now both Alice and Bob see the same products: Product A' (modified), Product B, and Product D

My questions are:

Upvotes: 0

Views: 368

Answers (1)

Will Shaver
Will Shaver

Reputation: 13071

Ahh temporal data, the bane of database developers everywhere.

Fortunately this is arguably easier in mongodb than other relational dbs.

If you can make the assumption that you'll have at most ONE unpublished version this problem is much simpler than if you can have different users editing unpublished versions.

Assuming you've got some standard things in your schema:

{ 
 _id: ObjectId
 name: String,
 CreatedDate: Date,
 Price: Number
}

You need to add a sub-document with a duplicate of any field editable by the user. It also will contain a flag for deletion.

{ 
 _id: ObjectId
 name: String,
 createdDate: Date,
 price: Number,
 revised:     {      
     name: String,
     createdDate: Date,
     price: Number,
     deleted: Boolean,
     }
}

When a user goes to edit the product, you'll copy over the existing props into the 'revised' object. All edits go to that object. When you publish, you copy those items back to the base layer, and delete the 'revised' property.

If you have multiple users editing the document, and they can't see each other's edits you could make your revised document a bit more complicated

{ revised: { U1234: { name : ... }, U2345 : { name: ... } } }

Where each user has a separate copy. Of course when one user publishes it could delete the entity entirely. I would of course recommend adding a 'deleted' flag to the root item instead of actually deleting it from the db, unless these objects are HUGE. (Index the deleted flag of course.)

Upvotes: 1

Related Questions