mongodbmongodb-.net-drivermongodb-scala

Block a change field in mongoDB


I have a collection in MongoDB which makes an increase, the field was initially defined as an Integer, but I find that after the increase was converted to double.

But then I make an update of the document and see that changes to Long.

Is there any way to block these changes in Mongo?

Thanks in advance


Solution

  • Since MongoDB doesn't have a fixed schema per collection, there's no way to prevent such changes on the database side. Make sure that you use the same data type for the field everywhere, including its update operations. The C# driver is pretty smart about this.

    Be careful when working with the shell, it can be irritating. Per default, the mongo shell will treat every number as a double, e.g.:

    > db.Inc.find().pretty();
    { "_id" : 1, "Number" : 1000023272226647000 }
    // this number is waaayyy larger than the largest 32 bit int, but there's no
    // NumberLong here. So it must be double.
    > db.Inc.update({}, {$inc: {"Number" : 1 }});
    > db.Inc.find().pretty();
    { "_id" : 1, "Number" : 1000023272226647000 }
    // Yikes, the $inc doesn't work anymore because of precision loss
    

    Let's use NumberLong:

    > db.Inc.insert({"Number" : NumberLong("1000023272226647000")});
    > db.Inc.update({}, {$inc: {"Number" : 1}});
    > db.Inc.find();
    { "Number" : 1000023272226647000, "_id" : 1 }
    // Yikes! type conversion changed to double again! Also note 
    // that the _id field moved to the end
    

    Let's use NumberLong also in $inc:

    > db.Inc.insert({"Number" : NumberLong("1000023272226647000")});
    > db.Inc.update({}, {$inc: {"Number" : NumberLong("1")}});
    > db.Inc.find();
    { "_id" : 1, "Number" : NumberLong("1000023272226647001") }
    // This actually worked
    

    In C#, both of the following updates work, Number remains a long:

    class Counter { public long Number {get;set;} public ObjectId Id {get;set;} }
    var collection = db.GetCollection("Counter");
    collection.Insert(new Counter { Number = 1234 }); 
    collection.Update(Query.Null, Update<Counter>.Inc(p => p.Number, 1)); // works
    collection.Update(Query.Null, Update.Inc("Number", 1)); // works too