Evolving Documents in RavenDB

Changes in the application often result in modifications of underlying data structure. Properties need to be added, removed or renamed when your application adapt to the new business needs. Today you will see how RavenDB handles this use case and how this differs to a relational database.

This post is part of the RavenDB series. You can find the other parts here:

 

Add Properties

If you need more properties to store your data you simply add another property to your class. If you connect to RavenDB and load an existing document without that property it will automatically be set to the default value. When you call SaveChanges() the default value will be saved – unless you set it to another value.

As an example the book class should get a new property rating. The current documents look like this one:

All we need to do is add the property to the class, load the document and call SaveChanges():

The document will be altered to this one:

All other documents that where not “updated” don’t have the rating property. RavenDB is a document oriented database and don’t have a concept of a table. All documents are on their own and don’t have to share the same properties. To update all the books in the database you either can load the whole database or use the bulk update explained in Set Based Operations in RavenDB.

 

Remove Properties

Properties that are missing in your object but are present in the document are ignored. Therefore you only have to delete the property in your class, load the document and call SaveChanges(). When you no longer need the ISBN property you just alter the book class:

The next time you call SaveChanges() after loading a book the document will no longer containing the ISBN property:

 

Rename Properties

When you rename a property in your class RavenDB will see this as if you removed the property with the old name and added a property with the new name. While the old property of the document will be removed and a new one added your data will not be transferred. Therefore this approach won’t work for most users and we need to find a better one.

While bulk updates are optional when we add or remove a property they are needed when we rename it. In this case we want all documents use the new name of the property and not build an endless mapping between old and new name. All we need is an index containing all the documents we want to update and then use the UpdateByIndex() method of the DatabaseCommands class.

This code renames the property Pages to PrintedPages for all documents in the index AllBooks:

Gian Maria Ricci describes a great walk through on the whole process in his blog post “Rename a property in RavenDb“.

 

Wrong Version = Data Lost

The flexibility of RavenDB is great for most use cases. But this changes as soon as you use the wrong version of your client application. Properties that are missing in your object but are present in the document are ignored (as explained above). As soon as you call SaveChanges() the document no longer contains the missing property. This effect happens when you want to remove the property and even if your client just missed an update…

To prevent such an event is not that simple. RavenDB can’t detect if you wanted do delete the property on purpose or if you use an outdated definition. Therefore you are on your own and have to implement a check in your client code. This can be as simple as to store a client version document in RavenDB and letting your client application check if this version matches the one of the client. This may sound like a hack but it is better than losing data. Please let me know if you have a better approach to this problem.

 

Next

In the next post you will get an overview of the new features in RavenDB 3. With improvements on the indexing performance, the new Java API and RavenFS for attachments there are many new and exciting topics for future blog posts.

10 thoughts on “Evolving Documents in RavenDB”

  1. Just to note, in 3.0, we will NOT be removing missing properties, so you don’t have the danger of data loss.
    We’ll keep the values for removed properties around until a user explicitly tells us what to do with them.

    Reply
    • Hi Ayende,
      That’s great and solves a big concern for the usage in production.

      Thanks,
      Johnny

      Reply
  2. Nice, but what if you want to change class name and/or namespace? What if this class is part of a collection in another document?

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.