我在Python中定义了以下管道。当标签包含
.
(例如 "1.2.3"
)时,我遇到了问题。
labels.{label}
变成 labels.1.2.3
$labels.{k}
变成 $labels.1.2.3
pipeline = [
{
"$match": {
"$and": [
{"deleted": {"$ne": True}},
{
"$or": [
{f"labels.{label}": {"$exists": True}} for label in label_list
]
}
]
}
},
{
"$project": {
"_id": 0,
"command": 1,
"matching_labels": {
k: f"$labels.{k}" for k in label_list
}
}
}
]
我询问了chatgpt,但它未能帮助解决问题。你能帮我一下吗?
我尝试使用
\.
来转义 .
以及 []
而不是 .
但都不起作用。
文件示例:
{
"_id": {
"$oid": "670cd0bae77a7a8a17abfb71"
},
"command": "show alarms ",
"original": "show alarms",
"labels": {
"critical": 2,
"rx": 1,
"failure": 1,
"6.5.3": 1,
"isis": 1,
"l2vpn": 1,
"chassis": 1,
"ncs-5501": 1,
"logs": 1,
"7.5.2": 1,
"hardware failure": 1,
"6.6.3": 1
},
"merged": true,
"finalised": true
}
$getField
可用于名称中包含句点 .
或美元 $
的字段。当该字段不存在时,$type
为 missing
。所以将其用于 $match
阶段。
对应的,在
$project
阶段,使用$setField
。或者正如我在下面所做的那样,我使用 $replaceWith
而不是 $project
。
以两个标签
"1.2.3"
和 "6.5.3"
为例,这将是聚合管道 - 每次我重复这两个标签的块时,您都可以在 Python 中将其替换为列表理解。
db.collection.aggregate([
{
"$match": {
"$expr": {
"$and": [
{ "$ne": ["$deleted", true]},
{
"$or": [
{
"$ne": [
{
"$type": {
"$getField": { "field": "1.2.3", "input": "$labels" }
}
},
"missing"
]
},
{
"$ne": [
{
"$type": {
"$getField": { "field": "6.5.3", "input": "$labels" }
}
},
"missing"
]
}
]
}
]
}
}
},
{ "$set": { "matching_labels": { "$literal": {} } } },
{
"$replaceWith": {
"command": "$command",
"matching_labels": {
"$mergeObjects": [
{
"$setField": {
"field": "1.2.3",
"input": "$matching_labels",
"value": {
"$getField": { "field": "1.2.3", "input": "$labels" }
}
}
},
{
"$setField": {
"field": "6.5.3",
"input": "$matching_labels",
"value": {
"$getField": { "field": "6.5.3", "input": "$labels" }
}
}
}
]
}
}
}
])
在这个 Mongo Playground 示例中,请注意,只有存在的字段才会在“matching_labels”中设置,因为如果
value
的 $setField
是 missing
,则不会设置该字段。
旁注:存储“未知”/动态字段名称及其值是一种反模式。它应该是名称-值对,如
labels: [{name: "1.2.3", value: 2}, {name: "other", value: 100}, {...}]
。了解属性模式。