建立动态MongoDB查询以更新dict中的嵌套值

时间:2018-07-17 15:58:16

标签: mongodb flask pymongo

这样考虑对象:

{
    "_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运算符吗?有没有一种方法可以动态地针对不同的徽章以增加内部等级?

谢谢!

注意:我首先尝试使用MongoEngine进行此操作,但似乎无法对其进行深入研究。

1 个答案:

答案 0 :(得分:0)

您无法执行此操作,因为badges是文档,而不是数组。尝试

 ...
 {"$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 }
)