更新mongo 3.5的嵌套数组中的值 [英] Update value in nested array of mongo 3.5
问题描述
我想进行一次upsert呼叫以进行更新,以及将数据插入到mongo db的嵌套数组中.
这是我的mongo文件.
I want to make an upsert call to update as well as insert my data in nested array of mongo db.
This is my mongo document.
{
"_id" : "575",
"_class" : "com.spyne.sharing.SpyneShareUserProject",
"spyneSharePhotoList" : [
{
"_id" : "fxLO68XyMR",
"spyneShareUsers" : [
{
"_id" : "chittaranjan@eventila.com",
"selectedByClient" : false
},
{
"_id" : "chittaranjan@gmail.com",
"selectedByClient" : false
}
]
},
{
"_id" : "nVpD0KoQAI",
"spyneShareUsers" : [
{
"_id" : "chittaranjan@eventila.com",
"selectedByClient" : true
}
]
},
{
"_id" : "Pm0B3Q9Igv",
"spyneShareUsers" : [
{
"_id" : "chittaranjan@gmail.com",
"selectedByClient" : true
}
]
}
]
}
这里我的要求是,
Here my requirement is,
- 让我说我有一个ID,即 575 (_id)
- 然后,我将具有嵌套的数组ID,即 fxLO68XyMR (spyneSharePhotoList._id)
- 然后,我将使用嵌套的电子邮件ID作为ID,即 chittaranjan@eventila.com (spyneSharePhotoList.spyneShareUsers._id)和 selectedByClient (布尔值)
- lets say i have an ID i.e. 575 (_id)
- Then i will have the nested array ID i.e. fxLO68XyMR (spyneSharePhotoList._id)
- Then i will have nested email id as ID i.e. chittaranjan@eventila.com (spyneSharePhotoList.spyneShareUsers._id) and selectedByClient (boolean)
现在我要检查的是此ID(spyneSharePhotoList.spyneShareUsers._id)是否已存在于所需位置中,我要根据其更新布尔值,即 selectedByClient (是/否)电子邮件ID.
如果数组中不存在id,它将创建一个新条目.为
Now i want is to check if this ID (spyneSharePhotoList.spyneShareUsers._id) is already present in the desired location i want to update the boolean value i.e. selectedByClient (true / false) according to that email id.
If the id is not present in the array, the it will make a new entry. as
{
"_id" : "chittaranjan@gmail.com",
"selectedByClient" : false
}
列表中的 spyneShareUsers
请帮助我完成此任务.谢谢
in spyneShareUsers list.
Please help me to do this task. Thank you
推荐答案
这很可能不是最聪明的解决方案,但它应该可以工作:
Most likely this is not the smartest solution, but it should work:
shareUserProject = {
id: "575",
PhotoListId: "fxLO68XyMR",
ShareUserId: "chittaranjan_new@eventila.com"
}
db.collection.aggregate([
{ $match: { _id: shareUserProject.id } },
{
$facet: {
root: [{ $match: {} }],
update: [
{ $unwind: "$spyneSharePhotoList" },
{ $match: { "spyneSharePhotoList._id": shareUserProject.PhotoListId } },
{
$set: {
"spyneSharePhotoList.spyneShareUsers": {
$concatArrays: [
{
$filter: {
input: "$spyneSharePhotoList.spyneShareUsers",
cond: { $ne: ["$$this._id", shareUserProject.ShareUserId] }
}
},
[{
_id: shareUserProject.ShareUserId,
selectedByClient: { $in: [shareUserProject.ShareUserId, "$spyneSharePhotoList.spyneShareUsers._id"] }
}]
]
}
}
}
]
}
},
{ $unwind: "$root" },
{ $unwind: "$update" },
{
$set: {
"root.spyneSharePhotoList": {
$concatArrays: [
["$update.spyneSharePhotoList"],
{
$filter: {
input: "$root.spyneSharePhotoList",
cond: { $ne: ["$$this._id", shareUserProject.PhotoListId] }
}
}
]
}
}
},
{ $replaceRoot: { newRoot: "$root" } }
]).forEach(function (doc) {
db.collection.replaceOne({ _id: doc._id }, doc);
})
我没有检查MongoDB 3.5中是否所有操作符都可用
I did not check whether all operators are available in MongoDB 3.5
我的目标是处理聚合管道中的所有内容,最后只运行一个replaceOne()
.
My goal was to process everything in aggregation pipeline and run just a single replaceOne()
at the end.
这是基于 $ map 的另一种解决方案运算符:
Here another solution based on $map operator:
db.collection.aggregate([
{ $match: { _id: shareUserProject.id } },
{
$set: {
spyneSharePhotoList: {
$map: {
input: "$spyneSharePhotoList",
as: "photoList",
in: {
$cond: {
if: { $eq: [ "$$photoList._id", shareUserProject.PhotoListId ] },
then: {
"_id": "$$photoList._id",
spyneShareUsers: {
$cond: {
if: { $in: [ shareUserProject.ShareUserId, "$$photoList.spyneShareUsers._id" ] },
then: {
$map: {
input: "$$photoList.spyneShareUsers",
as: "shareUsers",
in: {
$cond: {
if: { $eq: [ "$$shareUsers._id", shareUserProject.ShareUserId ] },
then: { _id: shareUserProject.ShareUserId, selectedByClient: true },
else: "$$shareUsers"
}
}
}
},
else: {
$concatArrays: [
"$$photoList.spyneShareUsers",
[ { _id: shareUserProject.ShareUserId, selectedByClient: false } ]
]
}
}
}
},
else: "$$photoList"
}
}
}
}
}
}
]).forEach(function (doc) {
db.collection.replaceOne({ _id: doc._id }, doc);
})
您还可以通过两次更新获得相同的结果:
You can achieve the same result also with two updates:
shareUserProject = {
id: "575",
PhotoListId: "fxLO68XyMR_x",
ShareUserId: "chittaranjan_new@gmail.com"
}
ret = db.collection.updateOne(
{ _id: shareUserProject.id },
{ $pull: { "spyneSharePhotoList.$[photoList].spyneShareUsers": { _id: shareUserProject.ShareUserId } } },
{ arrayFilters: [{ "photoList._id": shareUserProject.PhotoListId }] }
)
db.collection.updateOne(
{ _id: shareUserProject.id },
{ $push: { "spyneSharePhotoList.$[photoList].spyneShareUsers": { _id: shareUserProject.ShareUserId, selectedByClient: ret.modifiedCount == 1 } } },
{ arrayFilters: [{ "photoList._id": shareUserProject.PhotoListId }] }
)
这篇关于更新mongo 3.5的嵌套数组中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!