MongoDB:将元素添加到包含在另一个字段上计算的字段的对象的数组的内部数组

MongoDB: add element to an inner array of array with an object that contains field calculated on another field

我有这个文件:

{
"_id" : ObjectId("626c0440e1b4f9bb5568f542"),
"ap" : [ 
    {
        "ap_id" : ObjectId("000000000000000000000001"),
        "shop_prices" : [ 
            {
                "shop_id" : ObjectId("000000000000000000000097"),
                "price" : 102
            }
        ]
    }
],
"bc" : [ 
    {
        "bc_id" : ObjectId("000000000000000000000003"),
        "price" : 102
    }, 
    {
        "bc_id" : ObjectId("000000000000000000000004"),
        "price" : 104
    }
],
"stock_price" : 70
}

我的需要是最终向 ap.shop_prices 添加一个元素(如果此结构不存在):

{
    "shop_id" : ObjectId("000000000000000000000096"),
    "price" : 104
}

价格为 bc.price 其中 bc.bc_id = ObjectId("000000000000000000000004")

这是我第一次(未成功)尝试:

updateMany(
   {
       "_id": {"$eq": ObjectId("626c0421e1b4f9bb5568f531")},
       "ap":{
           $elemMatch:{
                "ap_id":{$in:[ObjectId("000000000000000000000001")]},
                "shop_prices.shop_id":{$ne:ObjectId("000000000000000000000096")}
           }
       },
       "bc.bc_id": ObjectId("000000000000000000000003")
   },
   [
     {"$set": 
        {"ap.$.shop_prices": 
            {"$cond": 
                [{"$in": [ObjectId("000000000000000000000096"), "$ap.$.shop_prices.shop_id"]}, "$ap.$.shop_prices",
                    {"$concatArrays": 
                        ["$ap.$.shop_prices",
                            [{"shop_id": ObjectId("000000000000000000000096"), "price": ???}]
                        ]
                    }
                ]
             }
         }
      }
    ]
)

提前致谢

你可以做到:

  • 使用 $project
  • 查找与您的请求相关的 bc
  • 在 $set 运算符中使用 $map

这应该是解决方案:

    db.getCollection('test').update({
    "ap": {
        $elemMatch: {
            "ap_id":{$in:[ObjectId("000000000000000000000001")]},
            "shop_prices.shop_id":{$ne:ObjectId("000000000000000000000096")}
        }
    },
    "bc.bc_id": ObjectId("000000000000000000000004")
},
[
    {
        $project: {
            ap: 1, 
            bc: 1,
            stock_price: 1,
            current_bc: { 
                $arrayElemAt: [ {
                    $filter: {
                        input: "$bc",
                        as: "curr_bc",
                        cond: {$eq: ["$$curr_bc.bc_id", ObjectId("000000000000000000000004")]}
                    }
                }, 0 ] 
            }
        }
    },
    {
        $set: {
            "ap": {
                "$map": {
                    input: "$ap",
                    as: "current_ap",
                    in: {
                        $cond: [
                            {$eq: [ObjectId("000000000000000000000001"), "$$current_ap.ap_id"]}, 
                            {  
                                "$mergeObjects": [
                                    "$$current_ap",
                                    {"shop_prices": {$concatArrays: ["$$current_ap.shop_prices", [{"shop_id": ObjectId("000000000000000000000096"), "price": "$current_bc.price"}]]}}
                                ]
                            },
                            "$$current_ap"
                        ]
                    }
                }
            }
        }
    }
])