Handling Collection Events with MongoDB C # Driver (v2.0)

Playing with the new MongoDB driver (v2.0) was quite challenging. Most of the examples you find on the Internet still refer to the legacy driver. The reference manual for v2.0 on the Mongo official site is at least "concise".

I'm trying to do a simple thing: detect when a collection has changed in order to forward a C # event to my server application .

For this I found the following C # example (see below) which I am trying to convert to a new API.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace TestTailableCursor {
    public static class Program {
        public static void Main(string[] args) {
            try {
                var server = MongoServer.Create("mongodb://localhost/?safe=true");
                var database = server["test"];

                if (database.CollectionExists("capped")) {
                    database.DropCollection("capped");
                }
                var collectionOptions = CollectionOptions.SetCapped(true).SetMaxDocuments(5).SetMaxSize(10000);
                var commandResult = database.CreateCollection("capped", collectionOptions);
                var collection = database["capped"];

                // to test the tailable cursor manually insert documents into the test.capped collection
                // while this program is running and verify that they are echoed to the console window

                // see: http://www.mongodb.org/display/DOCS/Tailable+Cursors for C++ version of this loop
                BsonValue lastId = BsonMinKey.Value;
                while (true) {
                    var query = Query.GT("_id", lastId);
                    var cursor = collection.Find(query)
                        .SetFlags(QueryFlags.TailableCursor | QueryFlags.AwaitData)
                        .SetSortOrder("$natural");
                    using (var enumerator = (MongoCursorEnumerator<BsonDocument>) cursor.GetEnumerator()) {
                        while (true) {
                            if (enumerator.MoveNext()) {
                                var document = enumerator.Current;
                                lastId = document["_id"];
                                ProcessDocument(document);
                            } else {
                                if (enumerator.IsDead) {
                                    break;
                                }
                                if (!enumerator.IsServerAwaitCapable) {
                                    Thread.Sleep(TimeSpan.FromMilliseconds(100));
                                }
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }

            Console.WriteLine("Press Enter to continue");
            Console.ReadLine();
        }

        private static void ProcessDocument(BsonDocument document) 
        {
            Console.WriteLine(document.ToJson());
        }
    }
}

      

Several (related) questions:

  • Is this the correct approach with a new driver?
  • If so, how to set the collection options (like SetCap in the above example). The new API includes something called "CollectionSettings" that seems completely unrelated.
  • Am I the only option to rely on the old driver?

Thank you for your help.

+3


source to share


1 answer


Am I the only option to rely on an outdated driver?

Not.

[...] how to set collection parameters (eg SetCap in the example above). The new API includes something called "CollectionSettings" which seems completely unrelated.

Now CreateCollectionSettings

. CollectionSettings

is a parameter for the driver, that is, a way to specify the default behavior for each collection. CreateCollectionOptions

can be used like this:

db.CreateCollectionAsync("capped", new CreateCollectionOptions 
      { Capped = true, MaxDocuments = 5, MaxSize = 10000 }).Wait();

      



Is this the correct approach with a new driver?

I think that tail cursors are a feature of the database and it always makes sense to avoid polling.

I converted the gist of the code and it seems to work on my machine and trade;

Be careful when using .Result

and.Wait()

in a web or UI app.

private static void ProcessDocument<T>(T document)where T : class
{
    Console.WriteLine(document.ToJson());
}

static async Task Watch<T>(IMongoCollection<T> collection) where T: class
{ 
    try {
        BsonValue lastId = BsonMinKey.Value;
        while (true) {
            var query = Builders<T>.Filter.Gt("_id", lastId);

            using (var cursor = await collection.FindAsync(query, new FindOptions<T> { 
                CursorType = CursorType.TailableAwait, 
                Sort = Builders<T>.Sort.Ascending("$natural") }))
            {
                while (await cursor.MoveNextAsync())
                {
                    var batch = cursor.Current;
                    foreach (var document in batch)
                    {
                        lastId = document.ToBsonDocument()["_id"];
                        ProcessDocument(document);
                    }
                }
            }
        }
    }
    catch (Exception ex) {
        Console.WriteLine("Unhandled exception:");
        Console.WriteLine(ex);
    }
}

      

+3


source







All Articles