当字段名包含“.”时如何引用mongodb管道中的子字段

问题描述 投票:0回答:1

我在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
}
python mongodb pipeline
1个回答
0
投票

$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}, {...}]
。了解属性模式

© www.soinside.com 2019 - 2024. All rights reserved.