【问题标题】:build dynamic MongoDB query to update nested value in dict构建动态 MongoDB 查询以更新 dict 中的嵌套值
【发布时间】:2018-07-17 15:58:15
【问题描述】:

考虑这样的对象:

{
    "_id" : ObjectId("5b4dbf3541e5ae6de394cc99"),
    "active" : true,
    "email" : "admin@something.eu",
    "password" : "$2b$12$5qqD3ZulKI7S6j.Wx513POpCNWRMppE.vY4.3EIZedm109VUPqXoi",
    "badges" : {
        "cnc" : {
            "lvl" : "0"
        },
        "laser" : {
            "lvl" : "0"
        },
        "impression3d" : {
            "lvl" : "0"
        },
        "maker" : {
            "lvl" : "0"
        },
        "electronique" : {
            "lvl" : "0"
        },
        "badge" : {
            "lvl" : 1
        }
    },
    "roles" : [ 
        ObjectId("5b4dbf3541e5ae6de394cc97")
    ]
}

我需要将 lvl 值更改为 0 到 5 之间的任何值,不一定是不规则增量。为此,父对象名称由变量传递,因此我正在尝试为要更改的徽章 lvl 构建动态查询。

目前我的 Flask 路线的结尾是这样的:

badge = quiz['badge']
C_user = current_user.get_id()
update = bdd.user.update({"_id": C_user, "badges": { '$elemMatch': {badges : badge}}}, {"$set": { "badges.$.lvl": 3 }}, upsert = True)

但是对于这种查询,我收到一条错误消息:

pymongo.errors.WriteError: The positional operator did not find the match needed from the query.

我是否完全错误地认为我需要使用 $elemMatch 运算符?有没有办法动态定位不同的徽章以增加内部 lvl?

谢谢!

注意:我第一次尝试使用 MongoEngine,但似乎无法深入研究。

【问题讨论】:

    标签: mongodb flask pymongo


    【解决方案1】:

    你不能这样做,徽章是一个文档,而不是一个数组。试试

     ...
     {"$set": { "badges.badge.lvl": 3 }} 
     ...
    

    但您必须为每个徽章字段明确执行此操作。 使用查询的方法是更新您的方案,例如

    ...
    "badges" : [
        {name:"cnc", 
            "lvl" : "0"
        },
        {"name":"laser",
            "lvl" : "0"},
        ...
        ]
        ...
    

    编辑:随着您的计划的一些更新,这是实现目标的一种方法:

    新数据架构:

    { 
        "_id" : ObjectId("5b4dbf3541e5ae6de394cc99"), 
        "active" : true, 
        "email" : "admin@something.eu", 
        "password" : "$2b$12$5qqD3ZulKI7S6j.Wx513POpCNWRMppE.vY4.3EIZedm109VUPqXoi", 
        "badges" : [
            {
                "name" : "cnc", 
                "lvl" : "0"
            }, 
            {
                "name" : "laser", 
                "lvl" : "5"
            }, 
            {
                "name" : "impression3d", 
                "lvl" : "0"
            }, 
            {
                "name" : "maker", 
                "lvl" : "0"
            }, 
            {
                "name" : "electronique", 
                "lvl" : "0"
            }, 
            {
                "name" : "badge", 
                "lvl" : 1
            }
        ], 
        "roles" : [
            ObjectId("5b4dbf3541e5ae6de394cc97")
        ]
    }
    

    这里是更新查询:

    db['02'].update(
       {_id: ObjectId("5b4dbf3541e5ae6de394cc99")}, // <= here you filter your documents
       { $set: { "badges.$[elem].lvl": "10" } },  // <= use of positionnal operator with identifier, needed for arrayFilters. elem is arbitraty
       { arrayFilters: [ { "elem.name": "laser" } ], // <= update only elements in array that match arrayFilters. 
         upsert: true }
    )
    

    【讨论】:

    • 感谢@matthPen,此时查看数据方案不是问题,但我现在怀疑如何构建我们的集合:我们的数据看起来超级简单,一个用户集合,有基本登录信息和角色。我们需要能够手动或通过他们成功回答测验将徽章归因于每个用户。如上所示,徽章应该能够具有多个级别。徽章集合的嵌入式文档是否允许我们增加用户文档中的级别,还是引用它们更好?再次感谢!
    • 不需要继续引用,我已经用一个更明确的例子更新了我的答案,即使用数组而不是文档字段。此外,在这种用途中使用数组更符合逻辑,并且引用会增加复杂性。
    猜你喜欢
    • 2016-04-02
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    相关资源
    最近更新 更多