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"
]
}
}
}
}
}
])
我有这个文件:
{
"_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"
]
}
}
}
}
}
])