MongoDB: $set specific fields for a document array elements only if not null
MongoDB: $set specific fields for a document array elements only if not null
我有一个 collection 包含以下文件(例如):
{
"_id": {
"$oid": "61acefe999e03b9324czzzzz"
},
"matchId": {
"$oid": "61a392cc54e3752cc71zzzzz"
},
"logs": [
{
"actionType": "CREATE",
"data": {
"talent": {
"talentId": "qq",
"talentVersion": "2.10",
"firstName": "Joelle",
"lastName": "Doe",
"socialLinks": [
{
"type": "FACEBOOK",
"url": "https://www.facebook.com"
},
{
"type": "LINKEDIN",
"url": "https://www.linkedin.com"
}
],
"webResults": [
{
"type": "VIDEO",
"date": "2021-11-28T14:31:40.728Z",
"link": "http://placeimg.com/640/480",
"title": "Et necessitatibus",
"platform": "Repellendus"
}
]
},
"createdBy": "DEVELOPER"
}
},
{
"actionType": "UPDATE",
"data": {
"talent": {
"firstName": "Joelle new",
"webResults": [
{
"type": "VIDEO",
"date": "2021-11-28T14:31:40.728Z",
"link": "http://placeimg.com/640/480",
"title": "Et necessitatibus",
"platform": "Repellendus"
}
]
}
}
}
]
},
{
"_id": {
"$oid": "61acefe999e03b9324caaaaa"
},
"matchId": {
"$oid": "61a392cc54e3752cc71zzzzz"
},
"logs": [....]
}
一个简单的细分:我在collection中有很多objects像这样的。它们是一种审计日志,用于对其他文档采取的操作,'Match(es)'。例如 CREATE
+ 数据,UPDATE
+ 数据等
如您所见,文档的 logs
字段是一个 objects 的数组,每个都描述了这些操作中的一个。
data
对于每个操作 可能包含也可能不包含 特定字段,这反过来也可以是 objects 的数组:socialLinks
和 webResults
.
我正在尝试从 所有 这些具有指定匹配 ID 的文档中删除敏感数据。
对于每个文档,我想遍历 logs
数组字段,并更改特定字段的值 只有当它们存在时 ,例如:将 firstName
更改为*****
,与 lastName
相同,如果出现的话。另外,遍历 socialLinks
数组(如果存在),对于其中的每个元素,如果字段 url
存在,也将其更改为 *****
。
到目前为止,我已尝试对此查询进行许多细微的修改:
$set: {
'logs.$[].data.talent.socialLinks.$[].url': '*****',
'logs.$[].data.talent.webResults.$[].link': '*****',
'logs.$[].data.talent.webResults.$[].title': '*****',
'logs.$[].data.talent.firstName': '*****',
'logs.$[].data.talent.lastName': '*****',
},
还有一些人使用这种聚合查询:
[{
$set: {
'talent.socialLinks.$[el].url': {
$cond: [{ $ne: ['el.url', null] },'*****', undefined],
},
},
}]
导致如下错误: message: "The path 'logs.0.data.talent.socialLinks' must exist in the document in order to apply array updates.",
但我无法让它工作...:(
希望得到有关如何准确实现这种 set-only-if-exists 行为的解释。
一个工作示例也将不胜感激,谢谢。
建议使用 $\[<indentifier>\]
(filtered positional operator) and arrayFilters
更新数组字段中的嵌套文档。
在arrayFilters
中,用$exists
检查是否存在符合条件的文档并进行更新。
db.collection.update({},
{
$set: {
"logs.$[a].data.talent.socialLinks.$[].url": "*****",
"logs.$[b].data.talent.webResults.$[].link": "*****",
"logs.$[b].data.talent.webResults.$[].title": "*****",
"logs.$[c].data.talent.firstName": "*****",
"logs.$[d].data.talent.lastName": "*****",
}
},
{
arrayFilters: [
{
"a.data.talent.socialLinks": {
$exists: true
}
},
{
"b.data.talent.webResults": {
$exists: true
}
},
{
"c.data.talent.firstName": {
$exists: true
}
},
{
"d.data.talent.lastName": {
$exists: true
}
}
]
})
我有一个 collection 包含以下文件(例如):
{
"_id": {
"$oid": "61acefe999e03b9324czzzzz"
},
"matchId": {
"$oid": "61a392cc54e3752cc71zzzzz"
},
"logs": [
{
"actionType": "CREATE",
"data": {
"talent": {
"talentId": "qq",
"talentVersion": "2.10",
"firstName": "Joelle",
"lastName": "Doe",
"socialLinks": [
{
"type": "FACEBOOK",
"url": "https://www.facebook.com"
},
{
"type": "LINKEDIN",
"url": "https://www.linkedin.com"
}
],
"webResults": [
{
"type": "VIDEO",
"date": "2021-11-28T14:31:40.728Z",
"link": "http://placeimg.com/640/480",
"title": "Et necessitatibus",
"platform": "Repellendus"
}
]
},
"createdBy": "DEVELOPER"
}
},
{
"actionType": "UPDATE",
"data": {
"talent": {
"firstName": "Joelle new",
"webResults": [
{
"type": "VIDEO",
"date": "2021-11-28T14:31:40.728Z",
"link": "http://placeimg.com/640/480",
"title": "Et necessitatibus",
"platform": "Repellendus"
}
]
}
}
}
]
},
{
"_id": {
"$oid": "61acefe999e03b9324caaaaa"
},
"matchId": {
"$oid": "61a392cc54e3752cc71zzzzz"
},
"logs": [....]
}
一个简单的细分:我在collection中有很多objects像这样的。它们是一种审计日志,用于对其他文档采取的操作,'Match(es)'。例如 CREATE
+ 数据,UPDATE
+ 数据等
如您所见,文档的 logs
字段是一个 objects 的数组,每个都描述了这些操作中的一个。
data
对于每个操作 可能包含也可能不包含 特定字段,这反过来也可以是 objects 的数组:socialLinks
和 webResults
.
我正在尝试从 所有 这些具有指定匹配 ID 的文档中删除敏感数据。
对于每个文档,我想遍历 logs
数组字段,并更改特定字段的值 只有当它们存在时 ,例如:将 firstName
更改为*****
,与 lastName
相同,如果出现的话。另外,遍历 socialLinks
数组(如果存在),对于其中的每个元素,如果字段 url
存在,也将其更改为 *****
。
到目前为止,我已尝试对此查询进行许多细微的修改:
$set: {
'logs.$[].data.talent.socialLinks.$[].url': '*****',
'logs.$[].data.talent.webResults.$[].link': '*****',
'logs.$[].data.talent.webResults.$[].title': '*****',
'logs.$[].data.talent.firstName': '*****',
'logs.$[].data.talent.lastName': '*****',
},
还有一些人使用这种聚合查询:
[{
$set: {
'talent.socialLinks.$[el].url': {
$cond: [{ $ne: ['el.url', null] },'*****', undefined],
},
},
}]
导致如下错误: message: "The path 'logs.0.data.talent.socialLinks' must exist in the document in order to apply array updates.",
但我无法让它工作...:(
希望得到有关如何准确实现这种 set-only-if-exists 行为的解释。 一个工作示例也将不胜感激,谢谢。
建议使用 $\[<indentifier>\]
(filtered positional operator) and arrayFilters
更新数组字段中的嵌套文档。
在arrayFilters
中,用$exists
检查是否存在符合条件的文档并进行更新。
db.collection.update({},
{
$set: {
"logs.$[a].data.talent.socialLinks.$[].url": "*****",
"logs.$[b].data.talent.webResults.$[].link": "*****",
"logs.$[b].data.talent.webResults.$[].title": "*****",
"logs.$[c].data.talent.firstName": "*****",
"logs.$[d].data.talent.lastName": "*****",
}
},
{
arrayFilters: [
{
"a.data.talent.socialLinks": {
$exists: true
}
},
{
"b.data.talent.webResults": {
$exists: true
}
},
{
"c.data.talent.firstName": {
$exists: true
}
},
{
"d.data.talent.lastName": {
$exists: true
}
}
]
})