将项目附加到 PyMongo 中的 MongoDB 文档数组而不重新插入
Posted
技术标签:
【中文标题】将项目附加到 PyMongo 中的 MongoDB 文档数组而不重新插入【英文标题】:Append item to MongoDB document array in PyMongo without re-insertion 【发布时间】:2016-01-16 07:33:44 【问题描述】:我使用 MongoDB 作为 Python Web 应用程序 (PyMongo + Bottle) 的后端数据库。用户可以上传文件并在上传过程中选择“标记”这些文件。标签存储为文档中的列表,如下所示:
"_id" : ObjectId("561c199e038e42b10956e3fc"),
"tags" : [ "tag1", "tag2", "tag3" ],
"ref" : "4780"
我正在尝试允许用户将新标签附加到任何文档。我想出了这样的事情:
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)
(仅供参考;ref
密钥始终是唯一的。这也很容易成为 _id
。)
似乎应该有一种方法可以直接更新“标签”值,而无需拉回整个文档并重新插入。我在这里遗漏了什么吗?
任何想法都非常感谢:)
【问题讨论】:
【参考方案1】:在这里添加一点问题。
def create_course(course_name, course_teacher, username):
db.Accounts.find_one('username':username)['courses'].apppend('name':course_name, 'teacher':course_teacher)
这是尝试将课程添加到仪表板。由于某种原因它失败了,我不知道为什么
【讨论】:
不要添加问题作为答案;开始一个你自己的新问题。 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review【参考方案2】:您可以使用$push
collection_name.update_one('ref': ref, '$push': 'tags': new_tag)
您可以在单个查询中更新多个数组
collection_name.update_one('ref': ref, '$push': 'field1': value1, 'filed2': value2)
可以像下面这样推送值。
$push: <field1>: <value1>, ...
【讨论】:
【参考方案3】:已经有一些很好的答案是正确的,但我认为以这种方式编写 update_tags 更好,更有用:
def update_tags(ref, *args):
coll.update_one(ref, '$push': 'tags': '$each': args)
这样你既可以添加一个标签也可以添加多个标签:
>> 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)
【讨论】:
【参考方案4】:你可以这样做
1) 如果要追加单个条目
def update_tags(ref, new_tag):
coll.update('ref': ref, '$push': 'tags': new_tag)
例如:
"_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) 如果要追加多个条目
def update_tags(ref, new_tag):
coll.update('ref': ref, '$pushAll': 'tags': new_tag) #type of new_tag is list
例如:
"_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"
注意:如果密钥不存在,则 mongo 将创建新密钥。
【讨论】:
pymongo.errors.WriteError:未知修饰符:$pushAll$pushAll
不适用于将多个值附加到数组。使用 $push
和 $each
修饰符将多个值附加到数组字段。 '$push': 'tags': '$each': new_tags_array
【参考方案5】:
只是添加到@ssytvane答案,并回答@Guarav:如果它不存在,您可以添加“upsert = True”:
def update_tags(ref, new_tag):
coll.update('ref': ref, '$push': 'tags': new_tag, upsert = True)
或
def update_tags(ref, new_tag):
coll.update_one('ref': ref, '$push': 'tags': new_tag, upsert = True)
【讨论】:
这里的 ref 是什么? upsert(可选):当为 True 时,如果没有文档与查询匹配,则插入一个新文档。默认为假。 api.mongodb.com/python/2.9/api/pymongo/…【参考方案6】:您不需要先使用.update
方法和$push
运算符来检索文档。
def update_tags(ref, new_tag):
coll.update('ref': ref, '$push': 'tags': new_tag)
由于不推荐使用更新,如果您使用的是 pymongo 2.9 或更高版本,则应使用 find_one_and_update
或 update_one
方法
【讨论】:
两者有什么区别?只是返回值(文档与 UpdateResult 对象)?您什么时候使用其中一种? 如果 'tags' 字段不存在会怎样? 如果tags
字段不存在,则创建它。 @GauravOjha
会删除旧记录吗?
必须是数组,但在文档中属于对象类型,会弹出此错误以上是关于将项目附加到 PyMongo 中的 MongoDB 文档数组而不重新插入的主要内容,如果未能解决你的问题,请参考以下文章
使用 pymongo 将数据从 Mysql 迁移到 MongoDB
如何使用 html、pymongo 中的按钮更新 mongodb
如何使用 flask_pymongo 将数据从 mongodb 显示到烧瓶模板?