简体   繁体   English

在MongoDB中,当文档具有嵌入式文档时,为什么更新/查找精确文档失败?

[英]In MongoDB, why does updating/finding exact documents fail when the document has an embedded document?

I'm using pymongo for reference. 我正在使用pymongo供参考。

So if I have a document like this: 因此,如果我有这样的文档:

{
    'name': 'bill',
    'color': 'blue',
    'subdocument': {
        'title': 'Untitled',
        'content': 'Hello World',
    }
}

If I find this document doing db.users.find()[0] and then pass it as an argument to update, Mongo will not find the document to update unless I remove the subdocument. 如果我发现此文档正在执行db.users.find()[0],然后将其作为更新参数传递,则Mongo将不会找到要更新的文档,除非删除子文档。 Passing the found document to find_one also fails unless the subdocument is removed. 除非删除了子文档,否则将找到的文档传递给find_one也会失败。

I need to specify all the fields for the sake of optimized locking. 为了优化锁定,我需要指定所有字段。 How can I easily retrieve the document, update it, and pass the original fields as requirements for not having been changed? 如何轻松检索文档,更新文档以及将原始字段作为未更改的要求传递?

Since I primarily was interested in this for the purpose of optimistic locking, I have found a better solution than my original attempt, thanks to Scott from the MongoDB Users Group 由于我主要出于乐观锁定的目的对此感兴趣,因此,比起最初的尝试,我找到了一个更好的解决方案,这要归功于MongoDB用户组的 Scott

The solution is to use a "version" counter field, and only update if the field has not been changed. 解决方案是使用“版本”计数器字段,并且仅当该字段未更改时才更新。 Upon each update of the document, the query doing the updating should increment the counter. 在每次文档更新时,进行更新的查询都应增加计数器。 This is faster , since all of the fields don't have to be scanned and compared for the change to be made. 这样更快 ,因为不必扫描所有字段并进行比较以进行更改。

I believe you are encountering a deep bug in MongoDB . 我相信您在MongoDB中遇到了一个深层错误 You can see a similar issue in this bug . 您可以在此bug中看到类似的问题。

Embedded documents are compared as binary rather than compared as documents. 嵌入式文档被比较为二进制而不是文档。 So subdocument: {a:1,b:2} is different from subdocument:{b:2,a:1} even though they should not be. 因此, subdocument: {a:1,b:2}subdocument:{b:2,a:1}即使它们不应该如此。

See this comment for why this may be a problem. 请参阅此评论以了解为什么这可能是一个问题。

Of course, that first bug is both serious and well over a year old, so it's questionable that this will be fixed any time soon. 当然,第一个错误是严重的,而且已经存在了一年多,因此,是否有可能在不久的将来修复该错误是值得怀疑的。 In fact, it's currently unscheduled. 实际上,它目前未计划。

Did you put a '$set' term in? 您是否输入了“ $ set”项?

Here's what I did: 这是我所做的:

d = {
    'name': 'bill',
    'color': 'blue',
    'subdocument': {
        'title': 'Untitled',
        'content': 'Hello World',
    }
}

db.name.insert(d)
f = db.name.find_one({'name':'bill'})
print f
{u'color': u'blue', u'_id': ObjectId('4f8dbc834647df1428000002'), u'name': u'bill', u'subdocument': {u'content': u'Hello World', u'title': u'Untitled'}}

db.name.update(f, {'$set':{'name':'fred'}})

f = db.name.find_one({'name':'fred'})
print f
{u'color': u'blue', u'_id': ObjectId('4f8dbc834647df1428000002'), u'name': u'fred', u'subdocument': {u'content': u'Hello World', u'title': u'Untitled'}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM