Mongo Update Array & Skip Null Fields



我正在做一个Mongo updateMany()查询。

我的集合中一个文档的浓缩示例:

{
"CurrentVersion": 3,
"EntryHistory": [
{
"State": 0,
"ProposalPlan": [
{
"Description": "Test",
"State": 1,
"Proposals": [
{
"Subject": "Test",
"Body": "Test",
"Urls": [
{
"Description": "Link text",
"Address": "https://examplelink.com"
}
]
}
]
}
]
}
]
}

请假设我的测试数据只是显示结构,而不是集合和数组的实际大小。

我怎么能写我的updateMany()查询不出错,如果它在文档中遇到一个空字段?我只是希望它能在文档出现问题时继续更新。

下面是我写的查询:

db.collectionName.updateMany(
{ "ProposalPlan.State": 1 },
{
$set: {
"ProposalPlan.State": 3,
"ProposalPlan.Proposals.10.Urls.0.Address": "https://newlinkexample.com"
}
}
);

我的问题是,当我运行这个查询时,一些满足过滤条件的文档是"腐败的";并且有null或不存在的提案和/或null或不存在的url,所以我面临一个错误,如"MongoServerError:不能在元素{url: null}"中创建字段'0'。

我还尝试在try catch中包装上面的查询,因为我希望它在文档抛出错误后继续,但我看到它不是这样工作的。

我尝试添加到过滤器,这样我甚至不会尝试更新损坏的文档开始:

db.collectionName.updateMany(
{ "ProposalPlan.State": 1, "ProposalPlan.Proposals.10.Urls.0.Address": { $ne: null } },
{
$set: {
"ProposalPlan.State": 3,
"ProposalPlan.Proposals.10.Urls.0.Address": "https://newlinkexample.com"
}
}
);

但到目前为止,这些都没有奏效。上面的额外过滤器不会抛出错误,但没有更新任何内容,当我尝试使用findOne()过滤器时,它只是无限搜索,而不是抓取提案计划的许多记录之一。State为1,ProposalPlan.Proposals.10.Urls.0。地址不为空

1)选项1(+4.2聚合框架):

db.collection.update({},
[
{
$set: {
"EntryHistory": {
"$map": {
"input": "$EntryHistory",
"as": "e",
"in": {
"$mergeObjects": [
"$$e",
{
"ProposalPlan": {
"$map": {
"input": "$$e.ProposalPlan",
"as": "p",
"in": {
"$mergeObjects": [
"$$p",
{
"$cond": {
"if": {
"$eq": [
"$$p.State",
1
]
},
"then": {
State: 3,
Proposals: {
"$map": {
"input": "$$p.Proposals",
"as": "r",
"in": {
"$mergeObjects": [
"$$r",
{
"$cond": {
"if": {
"$eq": [
{
"$indexOfArray": [
"$$p.Proposals",
"$$r"
]
},
0// Index of Proposals

]
},
"then": {
"Urls": {
"$map": {
"input": "$$r.Urls",
"as": "u",
"in": {
"$mergeObjects": [
"$$u",
{
"$cond": {
"if": {
$and: [
{
"$eq": [
{
"$indexOfArray": [
"$$r.Urls",
"$$u"
]
},
2// Index of Urls

]
},
{
"$ne": [
"$$u.Address",
null
]
}
]
},
"then": {
Address: "Example new link"
},
"else": {}
}
}
]
}
}
}
},
"else": {}
}
}
]
}
}
}
},
"else": {}
}
}
]
}
}
}
}
]
}
}
}
}
}
])

解释道:

它将更新:

"ProposalPlan.State": 3,
"ProposalPlan.Proposals.0.Urls.2.Address": "new value"

(更改Peoposals.10为0,因为示例太大了…)

但是如果("ProposalPlan.Proposals.0.Urls.2.Address"== null)然后它将只更新:

"ProposalPlan.State": 3

游乐场


选项2 (arrayFilter) -也许这正是你需要的

db.collection.update({
"EntryHistory.ProposalPlan.State": 1,
"EntryHistory.ProposalPlan.Proposals.Urls.Address": {
$ne: null
}
},
{
$set: {
"EntryHistory.$[].ProposalPlan.$[x].State": 3,
"EntryHistory.$[].ProposalPlan.$[x].Proposals.0.Urls.2.Address": "NewAddress"
},
},
{
"arrayFilters": [
{
"x.State": 1
}
],
multi: true
})

操场2

解释道:

使用arrayFilters匹配提案计划与状态=1和更新提案[0]文档,其中Urls2地址值不为空

最新更新