Python 基于多个字段(包括嵌套字段)映射的Mongo追加到标准化字符串字段

Python 基于多个字段(包括嵌套字段)映射的Mongo追加到标准化字符串字段,python,arrays,mongodb,aggregation-framework,pymongo,Python,Arrays,Mongodb,Aggregation Framework,Pymongo,我收集了大量字段,如: { 'class': 'apple' }, { 'class': 'appl' }, { 'class': 'orange', 'nested': [ {'classification': 'app'}, {'classification': 'A', {'classification': 'orang'} ] }, { 'nested': [ {'classi

我收集了大量字段,如:

{
    'class': 'apple'
},
{
    'class': 'appl'
},
{
    'class': 'orange',
    'nested': [
        {'classification': 'app'},
        {'classification': 'A',
        {'classification': 'orang'}
    ]
},
{
    'nested': [
        {'classification': 'O'},
        {'classification': 'unknown'}
    ]
}
我还有一个Python字典映射字段值,如:

{
    'class': {
        'apple': 'a',
        'appl': 'a',
        'orange': 'o'
    },
    'nested.classification': {
        'app': 'a',
        'A': 'a',
        'orang': 'o',
        'O': 'o',
        'unknown': 'u'
    }
}
我正在尝试(在PyMongo中)更新我的MongoDB集合,以便从顶级
class
字段和嵌套
nested.classification
字段累积映射字符的字符串字段

在上述情况下,这将产生以下更新:

{
    'class': 'apple'
    'standard': 'a'
},
{
    'class': 'appl'
    'standard': 'a'
},
{
    'class': 'orange',
    'nested': [
        {'classification': 'app'},
        {'classification': 'A',
        {'classification': 'orang'}
    ]
    'standard': 'oaao'
},
{
    'nested': [
        {'classification': 'O'},
        {'classification': 'unknown'}
    ]
    'standard': 'ou'
}

我如何才能有效地在规模上做到这一点?在聚合框架中?

您可以通过3个步骤获得所需的结果

注意:MongoDB只能迭代数组,因此我们需要将您的字典转换为
{k:“key”,v:“value”}
数组(我们可以使用,但不值得)

  • 我们通过迭代Python
    class
    dictionary映射
    class
    字段
  • 我们通过迭代Python
    nested.classification
    dictionary映射
    nested分类
  • 我们将值映射为单个值
  • (可选)如果需要将其持久化,请运行
    $merge
    阶段
  • Disclamer:MongoDB>=4.2+我不确定此解决方案是否具有良好的扩展性

    db.collection.aggregate([
      {
        "$addFields": {
          standard: {
            $reduce: {
              input: [
                { k: "apple",  v: "a" },
                { k: "appl",   v: "a" },
                { k: "orange", v: "o" }
              ],
              initialValue: "",
              in: {
                $cond: [
                  {
                    $eq: ["$$this.k", "$class"]
                  },
                  "$$this.v",
                  "$$value"
                ]
              }
            }
          }
        }
      },
      {
        "$addFields": {
          standard: {
            $reduce: {
              input: {
                "$ifNull": [ "$nested", [] ]
              },
              initialValue: [ { v: "$standard" } ],
              in: {
                $concatArrays: [
                  "$$value",
                  {
                    $filter: {
                      input: [
                        { k: "app",     v: "a" },
                        { k: "A",       v: "a" },
                        { k: "orang",   v: "o" },
                        { k: "O",       v: "o" },
                        { k: "unknown", v: "u" }
                      ],
                      as: "nested",
                      cond: {
                        $eq: [ "$$this.classification", "$$nested.k" ]
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      },
      {
        "$addFields": {
          "standard": {
            $reduce: {
              input: "$standard.v",
              initialValue: "",
              in: {
                "$concat": [ "$$value", "$$this" ]
              }
            }
          }
        }
      },
      //Optional - If you need to persist it
      { 
        $merge: {
          into: "collection",
          on: "_id",
          whenMatched: "replace"
        }
      }
    ])