How to generate an _id field in Mongo DB composed from multiple fields?

Viewed 52

I'm working in C# against Mongo DB and using the C# Mongo DB driver.

Here is a very simplified version of my classes:

public class EntityBase
    {
        public Guid id { get; set; }
    }
public class VerionEntity : EntityBase
    {
        public int version { get; set; }
    }

Each time I need to create a new version of the entity, I get the next version value from a separate collection in Mongo; that works fine and no issue here.

So for example, I can have following 2 documents in related collection in the database:

{
  "_id": UUID('0ba8feaa-26e0-4773-b06a-18d7c147e9d5')
  "version": 1
},

{
  "_id": UUID('0ba8feaa-26e0-4773-b06a-18d7c147e9d5')
  "version": 2
}

The problem with the above is that since the _id property is unique in Mongo, I'm getting a duplicate key exception when I try to insert a new version.

What I would like to keep in the database is as follows:

{
  "_id": "0ba8feaa-26e0-4773-b06a-18d7c147e9d5_1"
  "id": UUID('0ba8feaa-26e0-4773-b06a-18d7c147e9d5')
  "version": 1
},

{
  "_id": "0ba8feaa-26e0-4773-b06a-18d7c147e9d5_2"
  "id": UUID('0ba8feaa-26e0-4773-b06a-18d7c147e9d5')
  "version": 2
}

Notes:

  1. I'm using a class map approach; i.e. I separate my model from Mongo DB, thus solution should be in the EntityClassMapper : IMongoClassMapper class.

  2. I'm familiar with the option to create a custom ID generator. I created such class but couldn't understand how to call it in EntityClassMapper. In debug, it reaches MyCustomGenerator.IsEmpty but it never stops in MyCustomGenerator.GenerateId, so I guess I'm wrong with how I call it in EntityClassMapper. Also note that since the code never reached MyCustomGenerator.GenerateId, I actually don't know if I can get access to the id and version class members, in order to compose the 'id_version' string that I want.

Here is my custom generator class:

class MyCustomGenerator : IIdGenerator
    {
        private static MyCustomGenerator __instance = new MyCustomGenerator ();

        public static MyCustomGenerator Instance => MyCustomGenerator .__instance;

        public object GenerateId(object container, object document)
        {
            // I assume that 'document' stands for my entity, right?
            // Or should I pull data from 'container'?
            return document.id + "_" + document.version;
        }

        public bool IsEmpty(object id)
        {
            return id == null;
        }
    }

and here is how I call it in EntityClassMapper:

cm.MapIdField("id") // I guess this is wrong
  .SetElementName("_id")
  .SetIdGenerator(MyCustomGenerator.Instance);

Any help will be much appreciated !

0 Answers
Related