【问题标题】:In PyMongo, how to get the _id of the document if found, else insert and get the _id of the inserted document在 PyMongo 中,如果找到,如何获取文档的 _id,否则插入并获取插入文档的 _id
【发布时间】:2015-09-17 06:06:02
【问题描述】:

例如:

我有一个收藏“故事” 其中每个文档的格式为:

{
  '_id': <default>
  'story': <some very long string which should be unique in the collection>
}

现在每当我有一个故事时,如果它已经存在于“故事”中,我想要它的“_id”,否则插入一个设置了“故事”字段的新文档,并获取它的“_id”

我能想到的是:

story = "this is a very long story"
id = stories_col.find_one_and_update({
    'story': story,
}, {
    'story': story,
}, upsert=True, return_document=ReturnDocument.AFTER)['_id']

这不是效率低下吗,因为它会更新(修改)文档,即使它不是必需的?这可以提高效率吗

【问题讨论】:

    标签: python mongodb python-2.7 pymongo


    【解决方案1】:

    您唯一可以做得更好的就是定义一个函数,例如:

    def make_sure_exists(story, stories_col):
        data = stories_col.find_one({'story': story})
        if data is not None:
            return data.['_id']
        return stories_col.insert_one({'story': story}).inserted_id
    

    除非你有足够新的 mongo 版本,在这种情况下你可以使用$setOnInsert 操作:

    story = "this is a very long story"
    id = stories_col.find_one_and_update({
        'story': story,
    }, {
        'story': { '$setOnInsert': story }
    }, upsert=True, return_document=ReturnDocument.AFTER)
    

    【讨论】:

    • 其实你可以做得更好
    • $setOnInsert 运算符从 2.4 开始就已经存在,现在已经“相当老了”,就像几年前一样。我认为您没有查看我提交的答案
    • 是的,我做到了。而且你的“相当老”的版本和我的完全不同。
    【解决方案2】:

    你是其中的一部分,使用$setOnInsert修改更新操作:

    story = "this is a very long story"
    id = stories_col.find_one_and_update({
        'story': story,
    }, {
        '$setOnInsert': { 'story': story }
    }, upsert=True, return_document=ReturnDocument.AFTER)
    

    这意味着如果文档匹配,则将“不执行实际”写入,因为此处唯一有效的操作是“插入时”。

    通常建议“始终”使用适合您操作的 update operators,因为您使用“始终”的“原始”对象会替换文档中没有它们的“所有内容”。

    【讨论】:

    • 不应该是这样吗:{ $setOnInsert: { &lt;field1&gt;: &lt;value1&gt;, ... } }?
    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 2017-02-10
    • 2016-11-19
    • 1970-01-01
    相关资源
    最近更新 更多