【问题标题】:MongoDB Aggregation: add field from an embedded document via a dynamic field pathMongoDB 聚合:通过动态字段路径从嵌入式文档中添加字段
【发布时间】:2020-02-28 19:12:16
【问题描述】:

我有一个聚合管道并且被困在舞台上。此时我有一个格式如下的文档:

{
  _id:ObjectId(5e3d326637df7e4dda73ec22),
  levelName:"Level 1",
  levelNames: {
    "Level 1":"5e567993b6ed4b7b4d2c044d"
    "Level 2":"5e567996a7826d45f836dfa3"
    "Level 3":"5e5679991f515a01c73e9006"
  }
}

我想添加一个 $addField/$set 阶段,它为我提供 levelNames 对象中条目的 ID 值,其键与根文档的 levelName 属性匹配。

我一直在尝试使用某种动态字段路径 ($concat: ["levelNames.", "$levelName"]) 但没有运气。这是我的 $addField 阶段:

/**
 * newField: The new field name.
 * expression: The new field expression.
 */
{
  currentLevelId: {
    $let: {
      vars: {
        levelPath: {
          $concat: ["levelNames.", "$levelName"]
        }
      },
      in: {
        currentLevelId: "$$levelPath"
      }
    }
  }
}

我得到的结果是:

{
  _id:ObjectId(5e3d326637df7e4dda73ec22),
  levelName:"Level 1",
  levelNames: {
    "Level 1":"5e567993b6ed4b7b4d2c044d"
    "Level 2":"5e567996a7826d45f836dfa3"
    "Level 3":"5e5679991f515a01c73e9006"
  }
  currentLevelId: {
    currentLevelId:"levelNames.Level 1"
  }
}

我试图让 currentLevelId 的结果为“5e567993b6ed4b7b4d2c044d”,所以我想要的输出是:

{
  _id:ObjectId(5e3d326637df7e4dda73ec22),
  levelName:"Level 1",
  levelNames: {
    "Level 1":"5e567993b6ed4b7b4d2c044d"
    "Level 2":"5e567996a7826d45f836dfa3"
    "Level 3":"5e5679991f515a01c73e9006"
  },
  currentLevelId: "5e567993b6ed4b7b4d2c044d"
}

有什么办法可以实现吗?

【问题讨论】:

  • 你能告诉我你的聚合的示例结果吗?
  • @bravemaster 没问题,我已经更新了问题。
  • 你能不能也更新一下你想要的输出。

标签: mongodb aggregation-framework


【解决方案1】:

使用这个:

db.collection.aggregate([
   { $set: { data: { $objectToArray: "$levelNames" } } },
   {
      $set: {
         currentLevelId: {
            $arrayElemAt: ["$data.v", { $indexOfArray: ["$data.k", "$levelName"] }]
         }
      }
   },
   { $unset: "data" }
])

Mongo playground

【讨论】:

  • 有没有办法直接从levelNames 获取值,而不是将其转换为数组并获取levelName 的索引?
  • 我不这么认为,因为字段名称是动态的并且在设计时是未知的。
  • 确实,字段路径名不能以'$'开头。
  • 感谢@WernfriedDomscheit - 在操场上完美运行,但是当我在我的机器上运行它时,第一阶段出现以下错误:"object [{"_bsontype":"ObjectID"," id":{"0":94,"1":86,"2":121,"3":132,"4":167,"5":130,"6":109,"7": 69,"8":248,"9":54,"10":223,"11":162}}] 不是有效的 ObjectId" 可能是我正在运行的 Mongo 版本的问题?跨度>
  • 您有ObjectId 对象或字符串作为数据吗?
【解决方案2】:

这里是聚合查询,

*

db.collection.aggregate([
    {
        $addFields: {
            warehouses: { $objectToArray: "$levelNames" }
        }
    },
    {
        $project: {
            levelName: 1,
            levelNames: 1,
            currentLevelId: {
                $filter: {
                    input: "$warehouses",
                    as: "item",
                    cond: { $eq: ["$$item.k", "$levelName"] }
                }
            },
        }
    },
    { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", { $arrayElemAt: ["$currentLevelId", 0] }] } } },
    {
        $project: {
            currentLevelId: "$v",
            levelName: true,
            levelNames: true,
        }
    }
])

*

【讨论】:

  • 谢谢 Nikhil - 我同意 Wernfried 的回答,但这看起来也不错,非常感谢。
猜你喜欢
  • 1970-01-01
  • 2021-10-24
  • 2020-09-18
  • 2014-11-03
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
相关资源
最近更新 更多