Discussion:
Duplicate Key and Field Order
Luís Lobo
2014-02-12 11:10:32 UTC
Permalink
Hi!

I've been having trouble with (I thought random) duplicate key errors in
mongo.And came to a conclusion that I hope helps others.

Imagine a 'foo' collection with objects like this one:

*{ "key": { "group_id": 1, "date_day": ISODate("2014-02-12T00:00:00Z")
}, counter: 0 }**
*
The collection has a unique index:

*> db.foo.ensureIndex({'key.group_id': 1, 'key.date_day': 1}, {unique:
true})*

If I perform:

*db.foo.update({"key": {"group_id": 1, "date_day": new
Date('2014-02-12')} }, {'$inc': {'counter': 1}}, true /* , true);**
*
I have no problemas and the outcome (as expected) is:

*> db.foo.find()**
**{ "_id" : ObjectId("52fb50302597bd0cde688216"), "key" : { "group_id" :
1, "date_day" : ISODate("2014-02-12T00:00:00Z") }, "counter" : 1 }**
*
But if I change the order of the fields in the key I get:

*> db.foo.update({"key": {"date_day": new Date('2014-02-12'),
"group_id": 1} }, {'$inc': {'counter': 1}}, true, true);**
**E11000 duplicate key error index: test.foo.$group_id_1_date_day_1 dup
key: { : 1.0, : new Date(1392163200000) }**
*

This makes some sense if you test this:

*> var k1 = {"date_day": new Date('2014-02-12'), "group_id": 1};**
**> var k2 = {"group_id": 1, "date_day": new Date('2014-02-12')};**
**> print(k1 == k2);**
**false**
*
I guess you need to be very careful with the order of fields in mongo.

The real strange part is that, if you perform bulk updates in the shell, something like:

*db.foo.update({}, {"$set": {"key.date_day": new Date()}})**
*
You _*may*_ end up with *'key'* being reordered - I couldn't reproduce it, but it happened to me in the past.

Awaitting your wise comments :)
Regards,
--
Luís Filipe Lobo <lobo-***@public.gmane.org>
--
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/***@public.gmane.org
To unsubscribe from this group, send email to
mongodb-user+unsubscribe-/***@public.gmane.org
See also the IRC channel -- freenode.net#mongodb

---
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongodb-user+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.
Luís Lobo
2014-02-12 11:12:22 UTC
Permalink
Post by Luís Lobo
*db.foo.update({"key": {"group_id": 1, "date_day": new
Date('2014-02-12')} }, {'$inc': {'counter': 1}}, true /* , true);**
*
Please ignore the '/*'
--
Luís Filipe Lobo <lobo-***@public.gmane.org>
--
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/***@public.gmane.org
To unsubscribe from this group, send email to
mongodb-user+unsubscribe-/***@public.gmane.org
See also the IRC channel -- freenode.net#mongodb

---
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongodb-user+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.
Andrew Ryder
2014-02-13 07:08:24 UTC
Permalink
Hi Luís!

Yes, this behaviour is to be expected given your index definition: *{'key.group_id':
1, 'key.date_day': 1}*

You should use the same syntax for the match in your update command.

In the update command you are using right now, it is must match the field
named "key" to the following document *precisely*: *{"group_id": 1,
"date_day": new Date('2014-02-12')}*
Which is not what you intend. Rather, you want to match 2 particular field
values in any order. Your current update is field order sensitive. It would
also behave erroneously if you added new fields to the "key" sub-document.

Your match criteria should be of similar form to your index:
*{"key.group_id": 1, "key.date_day": new Date('2014-02-12')}*

This way you'll find the order no longer matters. Other fields in the "key"
sub-document are also ignored.

By the way, the re-ordering of document fields you have observed is
definitely possible. The occurrence is not common, but can happen when
documents are moved or fields are modified. MongoDB does not guarantee the
preservation of field order. In light of this, I'd recommend you change
your update commands to be as I suggest above.

I hope this has cleared things up.

Kind regards,
Andrew
Post by Luís Lobo
Hi!
I've been having trouble with (I thought random) duplicate key errors in
mongo. And came to a conclusion that I hope helps others.
*{ "key": { "group_id": 1, "date_day": ISODate("2014-02-12T00:00:00Z") },
counter: 0 }*
true})*
*db.foo.update({"key": {"group_id": 1, "date_day": new Date('2014-02-12')}
}, {'$inc': {'counter': 1}}, true /* , true);*
*> db.foo.find()*
*{ "_id" : ObjectId("52fb50302597bd0cde688216"), "key" : { "group_id" : 1,
"date_day" : ISODate("2014-02-12T00:00:00Z") }, "counter" : 1 }*
1} }, {'$inc': {'counter': 1}}, true, true);*
*E11000 duplicate key error index: test.foo.$group_id_1_date_day_1 dup
key: { : 1.0, : new Date(1392163200000) }*
*> var k1 = {"date_day": new Date('2014-02-12'), "group_id": 1};**> var k2 = {"group_id": 1, "date_day": new Date('2014-02-12')};**> print(k1 == k2);**false*
I guess you need to be very careful with the order of fields in mongo.
*db.foo.update({}, {"$set": {"key.date_day": new Date()}})*
You *may* end up with *'key'* being reordered - I couldn't reproduce it, but it happened to me in the past.
Awaitting your wise comments :)
Regards,
--
--
--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongodb-user-/***@public.gmane.org
To unsubscribe from this group, send email to
mongodb-user+unsubscribe-/***@public.gmane.org
See also the IRC channel -- freenode.net#mongodb

---
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongodb-user+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.
Loading...