Search code examples
c#mongodbmongodb-.net-driver

In MongoDb, how can you set a value on an object in a array property?


My goal is to put a "deleted at" timestamp on specific object in an array of a document.

If the document looks like this:

{   
    "subdoc": [
        {
            "key": 1,
            "value": "abc",
            "isActive": true
        },
        {
            "key":5,
            "value": "ade",
            "isActive":true
        }
    ]
}

I would like to be able to say "look for the document that has subdoc.key == 5 and subdoc.value == "ade"; set subdoc.isActive to false and set subdoc.deleteAt = current db timestamp. With a resulting document like this:

{   
    "subdoc": [
        {
            "key": 1,
            "value": "abc",
            "isActive": true
        },
        {
            "key":5,
            "value": "ade",
            "isActive": false,
            "deletedAt": Timestamp(1425911075,1)
        }
    ]
}

Is this doable?

Update: After further review of the mongo docs, this does seem doable with the "$ (update)" operator. That gets me what I need, but I'm hoping for a less magical-strings way of doing this using the C# driver?

My working find/update looks like this:

// find
{
    "subdoc.key":"2",
    "subdoc.value":"ade"
}
// update
{   
    "$currentDate": {
        "subdoc.$.deleteAt": {
            "$type": "timestamp"
        }
    }
}

Update: I should clarify that this updated time stamp field is used for synchronization by many sometimes-connected mobile clients in a load-balanced environment (multiple web servers, multiple worker processes, and a mongo cluster) with a high transaction volume, which makes it crucial that this time stamp has a single point truth, is logically sequential in the context of the app, and is as high precision as possible (fractions of a second). Otherwise, records could be missed in a sync.

For the moment, I'm using the above approach to ensure time stamped values are generated by the mongo database instance. And I'm pretty satisfied with this approach.


Solution

  • See most recent update. A combination of the positional and $currentDate operators is serving my purpose.