Simple-MongoDB – Support for Regex and custom Id’s

So, it took a little bit longer than anticipated, but I just checked in support for regular expressions and custom Id’s support in references, in my C# based MongoDB driver, Simple-MongoDB. I had to add support for regexs to the Newtonsoft Json.Net library, so as of right now, Simple-MongoDB uses a custom dll for this, but I have uploaded the patch to Json.Net, so hopefully it will reach the main-branch in a couple of days.

Download here

Regular expressions

To make use of regular expressions you make use of the class SimoRegex. You can of course combine this with other criteria as well.

Code example – Regular expressions

[TestMethod]
public void Find_UsingRegex()
{
    var cn = CreateConnection();
    using (var session = new SimoSession(cn))
    {
        var entityStore = new SimoEntityStore(session, DbName);

        entityStore.Insert(new Person { Name = "Daniel", Age = 29 });
        entityStore.Insert(new Person { Name = "Daniel1", Age = 45 });
        entityStore.Insert(new Person { Name = "Daniel1", Age = 55 });
        entityStore.Insert(new Person { Name = "Daniel2", Age = 65 });
        entityStore.Insert(new Person { Name = "Sue", Age = 20 });

        var refetched = entityStore.FindOne<Person>(new { Age = 45, Name = new SimoRegex("^Dan.*1") });

        Assert.AreEqual(45, refetched.Age);
        Assert.AreEqual("Daniel1", refetched.Name);
    }
}

Custom Id’s in references

The supported Id-types when setting up references are now:

  • SimoId
  • Guid
  • int
  • long
  • string

Code example – SimoId

[TestMethod]
public void ParentChildReference_Example()
{
    var cn = CreateConnection();
    using (var session = new SimoSession(cn))
    {
        var entityStore = new SimoEntityStore(session, DbName);

        //The parent generates a new _id when created.
        //That _id is then used in the reference which is attached to the child.
        //After that, you just store the items.
        var parent = new Parent { Name = "Daniel" };
        var fatherReference = entityStore.Reference<Parent>(parent._id);
        var child = new Child { Name = "Isabell", FatherReference = fatherReference };

        //You could of course have created the reference manually, but then you loose the
        //use of the pluralizer, and have to role-this on your own.
        //new SimoReference { CollectionName = "Parents", Id = parent._id };

        entityStore.Insert(parent);
        entityStore.Insert(child);

        var refetchedChild = entityStore.FindOne<Child>(new { child._id });

        Assert.AreEqual(fatherReference.Id, refetchedChild.FatherReference.Id);
        Assert.AreEqual(fatherReference.CollectionName, refetchedChild.FatherReference.CollectionName);
    }
}

Code example – Guid as id
In this example I make use of Guid’s for identification. I do this in conjunction with anonymous types, but of course could have made the example cleaner by using static-typed Parent and Child as in the previous example.

[TestMethod]
public void ParentChildReference_CustomId_Example()
{
    var cn = CreateConnection();
    using (var session = new SimoSession(cn))
    {
        var entityStore = new SimoEntityStore(session, DbName);

        //This time we use anonymous type and custom Id's (Guids).
        var parent = new { _id = Guid.NewGuid(), Name = "Daniel" };
        var fatherReference = entityStore.Reference("Parent", parent._id);
        var child = new { _id = Guid.NewGuid(), Name = "Isabell", FatherReference = fatherReference };

        //You could of course have created the reference manually, but then you loose the
        //use of the pluralizer, and have to role-this on your own.
        //new SimoReference<Guid> { CollectionName = "Parents", Id = parent._id };

        entityStore.Insert("Parent", parent);
        entityStore.Insert("Child", child);

        var refetchedChild = entityStore.FindOne(infered: child, entityName: "Child", selector: new { child._id });

        Assert.AreEqual(fatherReference.Id, refetchedChild.FatherReference.Id);
        Assert.AreEqual(fatherReference.CollectionName, refetchedChild.FatherReference.CollectionName);
    }
}

That’s it for now. More to come. I will now focus on making it run with the latest version of MongoDB, enabling Safemode and to simplify the use of Entitystore.

//Daniel

About these ads

3 thoughts on “Simple-MongoDB – Support for Regex and custom Id’s

  1. Hi Daniel,

    I don’t know if you remember the comments about being able to create a proxy so reference to other collections could be lazy, but, I’ve got a little tidbit ready. It’s not pretty at the moment as it involved hacking into Simple-MongoDb a little, although really it only involves a small change to the JsonSerializerFactory. The other change would be to have a Registry for setting up how/where/which properties should be considered lazy and what particular data should be stored with them.

    Say you had:

    public class Person {
    public Guid _Id { get;set;}
    public Person Father {get;set;}
    }

    Father would be a candidate for its own collection and probably even a lazy reference.

    The registry could be setup as:

    Registry.For(key: x => x._Id, lazy: true, collection: “Person”);

    Now the interesting part, if you use a custom IContractResolver (even overriding the Default one works) you could store the reference to the Father entity as :

    class EntityReference
    {
    public string Collection { get; set; }
    public object Id { get; set; }
    }

    So using the ContractResolver you override the CreateProperty method, do a lookup on the registry to see if the specific type is supposed to be automatically a reference. If it is you return a JsonProperty pointing to a JsonConverter incharge of Reading/Writing EntityReference. If its a lazy loaded relation (known from the registry), a proxy can be returned with the necessary EntityReference for future loading, or, simply perform the loading of the reference inline.

    The same can be used for lists or dictionaries and with a little playing around with the Registry class, even inject some Where filtering for lists. Say something like a list of contacts (which are stored in their own collection) where the State property is set to active.

    Hope this makes sense to someone apart from me :)

    I’ve setup a simple unit test without the registry part, as that would require some extended playing around with the driver guts, but for the serialization of the reference i’ve got that part working. I’m going to continue with the proxy part and see how well that goes. If you want me to send you the test let me know.

    /Rei

    • Hi,

      Sounds interesting and something we could package in a separate lib/project within the solution. Why I don’t want to include it directly in the SimpleMongoDb.dll is that as of right now I don’t want dependencies on proxies etc. But, if we find it useful, of course we could lift it in.

      I’m happy to look at your solution.

      //Daniel

  2. Pingback: Simple-MongoDB – Part 2, Anonymous types, JSON, Embedded entities and references « Daniel Wertheim

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s