我有mongo db collection,我用自己的对象键覆盖_id键,而不是让mongo使用ObjectId str。
我的文档对象是这样的,
{'_id': {
'recipient': 'some-string',
'my-id': 'some str',
},
'data': {...}
}
出于某种原因,我可以在使用嵌入式文档时存储重复文档,因为它们是_id键。
我没有收到重复的密钥错误,当我upsert我的旧文档时,不会更新。不确定是什么导致了这一点。根据mongodoc,我可以使用嵌入对象作为键。
修改1
以下是来自mongo shell的示例查询
> dups = db.update_events.find({“timestamp”:1384890772.02277})。toArray()
[
{
"_id" : {
"campaign-id" : "5982",
"message-id" : "123@x.mailgun.org",
"event" : "delivered",
"recipient" : "a@a.com"
},
"timestamp" : 1384890772.02277,
"campaign-id" : "5982",
"event" : "delivered",
"campaigns" : [ ],
"delivery-status" : {
"description" : null,
"message" : "",
"code" : 0
},
"message" : {
"headers" : {
},
"size" : 2885,
"attachments" : [ ]
},
"dealership" : "RuHOYkYvwh",
"tags" : [
"RuHOYkYvwh"
],
"flags" : {
"is-system-test" : false,
"is-authenticated" : true,
"is-test-mode" : false
}
},
{
"_id" : {
"recipient" : "a@a.com",
"message-id" : "123@x.mailgun.org",
"event" : "delivered",
"campaign-id" : "5982",
},
"delivery-status" : {
"description" : null,
"message" : "",
"code" : 0
},
"message" : {
"attachments" : [ ],
"recipients" : [
],
"size" : 2885,
"headers" : {
}
},
"campaign-id" : "5982",
"tags" : [
"RuHOYkYvwh"
],
"campaigns" : [ ],
"event" : "delivered",
"timestamp" : 1384890772.02277,
"flags" : {
"is-system-test" : false,
"is-test-mode" : false,
"is-authenticated" : true
},
"dealership" : "RuHOYkYvwh"
}
]
> dups.length
2
这是我用来插入它的python代码,
MyCollection.update(item, item, upsert=True)
其中'item'是一个带有'_id'的python dict。
答案 0 :(得分:3)
问题是属性的顺序,即您的第一个文档是:
"_id" : {
"campaign-id" : "5982",
"message-id" : "123@x.mailgun.org",
"event" : "delivered",
"recipient" : "a@a.com"
},
你的第二个:
"_id" : {
"recipient" : "a@a.com",
"message-id" : "123@x.mailgun.org",
"event" : "delivered",
"campaign-id" : "5982",
},
MongoDB实际上将它们视为两个不同的对象。这就是为什么它们不是重复的原因。前段时间有一个关于这个问题的争论很大,关于这种情况是多么愚蠢,并且在某个地方有一个JIRA,但是,现在我的搜索能力让我失望。
下划线问题是python dicts没有排序,如果你想让它正常工作,你需要考虑别的东西。
答案 1 :(得分:1)
你在某处犯了错误。这是不可能的。 _id键在任何情况下都是唯一的。
显示您的代码,该代码不会引起重复键错误,因为此处显示错误:
db.a.remove()
db.a.insert({_id : {'recepient' : 1, 'my-id' : 2}, 'data' : 'aaa'})
db.a.insert({_id : {'recepient' : 1, 'my-id' : 2}, 'data' : 'bbb'})
E11000重复键错误索引:a.a。$ id dup key:{:{recepient: 1.0,my-id:2.0}}
db.a.insert({_id : {'recepient' : 1, 'my-id' : 3}, 'data' : 'bbb'})
请注意,整个值应该是唯一的,而不仅仅是您的my-id或recepient。
P.S 您无法更新_id密钥,因此以后您将无法更改收件人或my-id。
答案 2 :(得分:1)
Python不保证字典中键的顺序, 但MongoDB确实关心订单。插入或查询时的不同顺序意味着Sammaye所描述的不同文档。
您可以通过以下方式解决该问题:
a)使用Python的collection.OrderedDict(2.7中的新内容)
http://docs.python.org/2/library/collections.html#collections.OrderedDict
b)使用PyMongo的bson.son
http://docs.python.org/2/library/collections.html#collections.OrderedDict
使用上述任一对象创建'_id'键,插入文档中的键将与您在Python代码中使用的顺序相同。