A cautionary tale - mgo asserts

roger peppe roger.peppe at canonical.com
Thu Jun 9 07:35:36 UTC 2016


On 9 June 2016 at 01:20, Menno Smits <menno.smits at canonical.com> wrote:
> On 8 June 2016 at 22:36, John Meinel <john at arbash-meinel.com> wrote:
>>>
>>> ...
>>
>>
>>>
>>>
>>>   ops := []txn.Op{{
>>>       C: "collection",
>>>       Id: ...,
>>>       Assert: bson.M{
>>>           "some-field.A": "foo",
>>>           "some-field.B": 99,
>>>       },
>>>       Update: ...
>>>   }
>>>
>>>> ...
>>
>>
>> If loading into a bson.M is the problem, wouldn't using a bson.M to start
>> with also be a problem?
>
>
> No this is fine. The assert above defines that each field should match the
> values given. Each field is checked separately - order doesn't matter.
>
> This would be a problem though:
>
>   ops := []txn.Op{{
>       C: "collection",
>       Id: ...,
>       Assert: bson.M{"some-field": bson.M{
>           "A": "foo",
>           "B": 99,
>       },
>       Update: ...
>   }
>
>
> In this case, mgo is being asked to assert that some-field is an embedded
> document equal to a document defined by the bson.M{"A": "foo", "B": 99} map.
> This is what's happening now when you provide a struct value to compare
> against a field because the struct gets round-tripped through bson.M. That
> bson.M eventually gets converts to actual bson and sent to mongodb but you
> have no control of the field ordering that will ultimately be used.

Actually, this *could* be OK (I thought it was, in fact) if the bson encoder
sorted map keys before encoding like the json encoder does. As
it doesn't, using bson.M is indeed definitely wrong there.

This order-dependency of ostensibly order-independent objects really is an
unfortunate property of MongoDB.



More information about the Juju-dev mailing list