If you are interested in the trend? Subject NoSql you will also here something about MongoDB soon. What makes mongoDB interesting for me is the promised Performance (even If I didn’t reach the limits with normal data banks yet) and the promise to say goodbye to all this O/R Mapper stuff (here I reach the limits all the time).
Robert has blogged about RavenDB here.
Maybe you are now asking yourself: what’s the different between mongoDB and RavenDB?
(Beside the funny name (in german “mongo” means something like hillbilly).
In fact this subject is enough for an own blog post. To make it short: It seems like mongoDB is faster, it provides more languages and because of that the community is bigger while RavenDB has a way better integration and the .net scenery.
I prefer mongoDB because I can use it for free also for commercial projects.
So far… where is the Code?
Installation
-
Download mongoDB for Win, OSX, Solaris or Linux:
-
Only thing you have to do by yourself is to create the directory “C\data\db” It’s also possible to configure the pad but mongoDB won’t create one by himself
-
On windows it’s enough to unpack the Zip file and a double click on the mongodb.exe. If you like to you could start mongoDB as a Windows Service.
-
Easy isn’t it?
Code
-
Additionally we need the mongoDB.Net driver you will find here: http://www.mongodb.org/display/DOCS/CSharp+Language+Center
-
Now you have to link these two references:
- Now we are able to connect:
MongoServer server = MongoServer.Create(); // connect to localhost MongoDatabase demo = server.GetDatabase("demo"); // connect to database MongoCollection<User> users = demo.GetCollection<User>("users");
In line one we start to connect to localhost if nothing else is configured without username/keyword. Line three is going to pass a data bank back to us and line five a “chart”. At this point mongo acts like a ordinary data bank.
- Add files
//insert for (int i = 0; i < 10; i++) { var result = users.Insert<User>(new User { Name = "Karl", Age = 20 }); }
- Read files
var userResult = users.FindAll(); foreach (var item in userResult) { Console.WriteLine(string.Format("{0} - {1}",item.Name,item.Age)); }
- Data model
class User { public ObjectId _id { get; set; } public string Name { get; set; } public int Age { get; set; } public List<ObjectId> Tags { get; set; } }
I’ve used Objectld (belongs to the mongo driver) instead of Guid as type for the ID. The driver is able to handle Guid but it will be written coded BASE64 as a binary field into the data bank and I assume that the homemade Objectld is a lot quicker.
- n:m – relationship…
//setup second collection MongoCollection<User> tags = demo.GetCollection<User>("tags"); // add & get a new collecton tags.Drop(); List<Tag> initialTags = new List<Tag>() { new Tag("Cool"), new Tag("Fast"), new Tag("Jedi"), new Tag("Ninja") }; tags.InsertBatch(initialTags); //add tags to a user (many to many) foreach (var item in userResult) { var randomTags = initialTags.Take(new Random().Next(0, 4)).Select(x=>x._id).ToList(); // add some random tags item.Tags = new List<ObjectId>(randomTags); users.Save(item); // saves changes to mongo }
class Tag { public Tag(string name) { Name = name; } public ObjectId _id { get; set; } public string Name { get; set; } }
… they are possible as well if you link it with the ID’s. If it’s necessary to normalize your files is the question but in fact it’s possible.
Now we have two charts one includes users and the other one tags which are able to be sorted to the users. This example shows how to not work with NoSql data banks. (I recognized it afterwards). Usually I would sort the Tags to the user as a text and build be a Map/Reduce query if I want to count the Tags for example and that’s how this would look like.
How quick are you?
Performance tests are a little bit tricky because they are depending on so many things. But I was curious about what will happen if I create many elements and read them out.
So I’ve applied 10000 different user types, read them and deleted them afterwards:
int UsersToAdd = 10000; //setup some users Func<List<User>> getTestUsers = () => { var tmp = new List<User>(); for (int i = 0; i < UsersToAdd; i++) { tmp.Add(new User { Name = "Karl" + i, Age = 20 }); } return tmp; }; //insert Stopwatch insertTimer = new Stopwatch(); insertTimer.Start(); foreach (var item in getTestUsers()) { users.Insert<User>(item); } insertTimer.Stop(); Console.WriteLine(UsersToAdd + " users added in: " + insertTimer.ElapsedMilliseconds + "ms"); //bulk insert insertTimer.Start(); users.InsertBatch<User>(getTestUsers()); insertTimer.Stop(); Console.WriteLine(UsersToAdd + " users added in an Batch: " + insertTimer.ElapsedMilliseconds + "ms"); //parallel insert insertTimer.Start(); System.Threading.Tasks.Parallel.ForEach<User>(getTestUsers(), x => users.Insert<User>(x)); insertTimer.Stop(); Console.WriteLine(UsersToAdd + " users added parallel in: " + insertTimer.ElapsedMilliseconds + "ms"); //load all insertTimer.Start(); var all = users.FindAll(); insertTimer.Stop(); Console.WriteLine("all users loaded in: " + insertTimer.ElapsedMilliseconds + "ms"); //drop all insertTimer.Start(); users.Drop(); insertTimer.Stop(); Console.WriteLine("all users droped in: " + insertTimer.ElapsedMilliseconds + "ms");
And that is my result (4GB RAM QuadCore, HDD RAID5, no SSD)
Management
To manage mongoDB there are several Tools available. I used the MongoExplorer for now. The dressy Silverlight tool could be installed directly from the website.
Query
That’s also a subject that includes enough material for an own blog post. For now: mongoDB is complete guidable with Javascript. Many of my own questions are answered after I watched this presentation: