在不重新插入的情况下将项目附加到 PyMongo 中的 MongoDB 文档数组
Append item to MongoDB document array in PyMongo without re-insertion
我正在使用 MongoDB 作为 Python 网络应用程序 (PyMongo + Bottle) 的后端数据库。用户可以上传文件,并且可以选择在上传过程中 'tag' 这些文件。标签在文档中存储为列表,如下所示:
{
"_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
。)
似乎应该有一种方法可以直接更新 'tags' 值,而无需拉回整个文档并重新插入。我在这里遗漏了什么吗?
非常感谢任何想法:)
您不需要先使用检索文档,只需使用带有 $push
运算符的 .update
方法。
def update_tags(ref, new_tag):
coll.update({'ref': ref}, {'$push': {'tags': new_tag}})
由于更新已被弃用,如果您使用的是 pymongo 2.9 或更高版本,您应该使用 find_one_and_update
or the update_one
方法
只是添加到@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)
你可以简单地做
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 将创建新密钥。
有一些很好的答案是正确的,但我认为这样写 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)
您可以使用$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>, ... } }
在这里补充一点问题。
def create_course(course_name, course_teacher, username):
db.Accounts.find_one({'username':username})['courses'].apppend({'name':course_name, 'teacher':course_teacher})
这正在尝试将课程添加到仪表板。由于某种原因它失败了,我不知道为什么
我正在使用 MongoDB 作为 Python 网络应用程序 (PyMongo + Bottle) 的后端数据库。用户可以上传文件,并且可以选择在上传过程中 'tag' 这些文件。标签在文档中存储为列表,如下所示:
{
"_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
。)
似乎应该有一种方法可以直接更新 'tags' 值,而无需拉回整个文档并重新插入。我在这里遗漏了什么吗?
非常感谢任何想法:)
您不需要先使用检索文档,只需使用带有 $push
运算符的 .update
方法。
def update_tags(ref, new_tag):
coll.update({'ref': ref}, {'$push': {'tags': new_tag}})
由于更新已被弃用,如果您使用的是 pymongo 2.9 或更高版本,您应该使用 find_one_and_update
or the update_one
方法
只是添加到@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)
你可以简单地做
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 将创建新密钥。
有一些很好的答案是正确的,但我认为这样写 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)
您可以使用$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>, ... } }
在这里补充一点问题。
def create_course(course_name, course_teacher, username):
db.Accounts.find_one({'username':username})['courses'].apppend({'name':course_name, 'teacher':course_teacher})
这正在尝试将课程添加到仪表板。由于某种原因它失败了,我不知道为什么