0

The database schema of an application is rarely fixed, due to new development the schema has to change. This also applies to a schema-less solution like MongoDB. There is documentation on how to handle schema changes, i.e. if a property has been removed / renamed etc. My problem is how to query data after such a schema change.

This is best illustrated with an over-simplified example. Consider the class Person

public class Person //version 1.0
{
    public Guid Id {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

At the time of the first release, there is the ill-conceived assumption that no two people can have the same name. So in order to retrieve one person entity from the database, I would either find the record by ID, or call the method "Find"

 public class DbContext
 {
   public IEnumerable<T> Find(Expression<Func<T, bool>> expression)
   {
    return _mongoDocumentCollection.AsQueryable().Where(expression).ToList();
   }

  private readonly IMongoCollection<T> _mongoDocumentCollection;

  //implementation omitted
 }

An example of using Find:

new DbContext().Find(p => p.FirstName + p.LastName == "JohnDoe");

Here I thus query the collection using an expression. As previously mentioned, this code will not work for long since multiple people can have the same name. So instead we add a field with a user name.

public class Person //version 2.0
{
    public Guid Id {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public string UserName {get;set;}
}

When fetching a document written in v1.0 by id, we follow the strategy outlined here, which will programatically add the field UserName by concatenating the first and last names. However, doing

 new DbContext().Find(p => p.UserName == "JohnDoe");

will never find the document written in v1.0 since it does not contain the property UserName.

The business only wants documents to be replaced if they are actually changed, so writing a migration script is not a solution. This also implies that I can eventually have N different versions of the same class in the document collection, i.e. v1.0, v2.0, .... vN. What patterns / design strategies are for querying data after a schema change?

  • 3
    "The business only wants documents to be replaced if they are actually changed, so writing a migration script is not a solution." Why? – Vincent Savard Aug 7 '18 at 12:35
  • 1
    Not familiar with Mongo but can you do something like p.UserName == "..." || (p.UserName == null && (p.FirstName + p.LastName == "...")) – DaveG Aug 7 '18 at 12:39
  • 1
    It seems to me that when the decision is made not to add UserName to v1 Persons, the decision is also made that v1 Persons will not be searchable by the UserName that they purposely don't have. – Eric King Aug 7 '18 at 18:32
  • At the time of the first release, there is the ill-conceived assumption that no two people can have the same name o God... Fire your business analyst and the software designer. – Laiv Aug 8 '18 at 7:01
0

The best way to handle this depends alot on your needs and your situation, and really has little to do with mongodb.

If the DB is shared among multiple clients, all which are of different vintage, you have a real problem. Best of luck.

If you have a single (or close to it) program that operates on this database (or at least a small enough set you control the release lifetime of those programs) - then I suggest you VERSION your schema.

A technique I frequently use is (not always viable but often) - is on startup, read the schema version from the DB, and if its newer than you support, abort app startup. If its older than the current one, then create a new database, with the new version, and copy all the data over, performing a migration (reformatting the data as needed). [note also, a simple variation on this technique includes the schema version in the database name so you can keep the old database around for as long as needed].

Then - in effect - you always have (except for this startup logic) the latest version of the database. This produces the best, simplest, code base (because your application code is always reliably using the ONE version of the schema IT knows about).

Another (somewhat similar) but more widely used is ETL - you have DBAs responsible for scripting changes to your database, and just have them assure the data has been updated/converted before installing/starting your application.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.