Python 无需重新插入即可将项目附加到 PyMongo 中的 MongoDB 文档数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33189258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:58:56  来源:igfitidea点击:

Append item to MongoDB document array in PyMongo without re-insertion

pythonmongodbmongodb-querypymongo

提问by deadbits

I am using MongoDB as the back-end database for Python web application (PyMongo + Bottle). Users can upload files and optionally 'tag' these files during upload. The tags are stored as a list within the document, per below:

我使用 MongoDB 作为 Python Web 应用程序 (PyMongo + Bottle) 的后端数据库。用户可以上传文件,并可以在上传过程中选择“标记”这些文件。标签作为列表存储在文档中,如下所示:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}

I am trying to allow users to append new tags to any document. I came up with something like this:

我试图允许用户将新标签附加到任何文档。我想出了这样的事情:

def update_tags(ref, new_tag)
    # fetch desired document by ref key as dict
    document = dict(coll.find_one({'ref': ref}))
    # append new tag
    document['tags'].append(new_tag)
    # re-insert the document back into mongo
    coll.update(document)

(fyi; refkey is always unique. this could easily be _idas well.) It seems like there should be a way to just update the 'tags' value directly without pulling back the entire document and re-inserting. Am I missing something here?

(仅供参考;ref键总是唯一的。这也很容易_id。)似乎应该有一种方法可以直接更新“标签”值,而无需拉回整个文档并重新插入。我在这里错过了什么吗?

Any thoughts are greatly appreciated :)

任何想法都非常感谢:)

采纳答案by styvane

You don't need to use to retrieve the document first just use the .updatemethod with the $pushoperator.

您不需要先使用来检索文档,只需使用.update带有$push操作符的方法即可。

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}})

Since update is deprecated you should use the find_one_and_updateor the update_onemethod if you are using pymongo 2.9 or newer

由于更新已弃用,如果您使用的是 pymongo 2.9 或更高版本,则应使用find_one_and_updateupdate_one方法

回答by Kiluvya.A

Just to add to @ssytvane answer,and to answer @Guarav: you can add "upsert = True" if it does not exist:

只是为了添加到@ssytvane 答案,并回答@Guarav:如果它不存在,您可以添加“upsert = True”:

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True)

or

或者

def update_tags(ref, new_tag):
    coll.update_one({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True)

回答by Nikhil Fulzele

You can simply do

你可以简单地做

1) If you want to append single entry

1)如果你想附加单个条目

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}})

eg:

例如:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}
>> update_tags("4780", "tag4")
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
>> coll.find_one({"ref":"4780"})
{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" ],
    "ref" : "4780"
}

2) If you want to append multiple entries

2) 如果要附加多个条目

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$pushAll': {'tags': new_tag}}) #type of new_tag is list

eg:

例如:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}
>> update_tags("4780", ["tag5", "tag6", "tag7"])
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
>> coll.find_one({"ref":"4780"})
{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" , "tag5", "tag6", "tag7" ],
    "ref" : "4780"
}

Note: If the key is not already present, then mongo will create new key.

注意:如果密钥不存在,则 mongo 将创建新密钥。

回答by ArminMz

There had been some good answers that are correct but in my opinion writing update_tags this way is better and more usable:

有一些很好的答案是正确的,但在我看来,以这种方式编写 update_tags 更好,更有用:

def update_tags(ref, *args):
    coll.update_one(ref, {'$push': {'tags': {'$each': args}}})

this way you can do both appending one tag or appending many tags:

通过这种方式,您既可以附加一个标签,也可以附加多个标签:

>> update_tags(ref, 'tag5')
>> update_tags(ref, 'tag5', 'tag6')
>> list_of_new_tags = do_something_that_returns_list_of_tags()
>> update_tags(ref, *list_of_new_tags)