【问题标题】:Append item to MongoDB document array in PyMongo without re-insertion将项目附加到 PyMongo 中的 MongoDB 文档数组而不重新插入
【发布时间】: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。) 似乎应该有一种方法可以直接更新“标签”值,而无需拉回整个文档并重新插入。我在这里遗漏了什么吗?

任何想法都非常感谢:)

【问题讨论】:

    标签: python mongodb mongodb-query pymongo


    【解决方案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)
        

        【讨论】:

        【解决方案6】:

        您不需要先使用.update 方法和$push 运算符来检索文档。

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

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

        【讨论】:

        • 两者有什么区别?只是返回值(文档与 UpdateResult 对象)?您什么时候使用其中一种?
        • 如果 'tags' 字段不存在会怎样?
        • 如果tags 字段不存在,则创建它。 @GauravOjha
        • 会删除旧记录吗?
        • 必须是数组,但在文档中属于对象类型,会弹出此错误
        猜你喜欢
        • 2015-09-27
        • 2020-10-15
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-27
        • 1970-01-01
        相关资源
        最近更新 更多