首页 > 解决方案 > 仅在 mongodb 中为动态字段名称项目嵌套对象

问题描述

我有一个名为 logins 的 mongodb 集合。结构如下,

{
  id: 1,
  name: "N1",
  tasks: {
    project1: {
      task7: {
        count: 10
        time: 1.2
      },
      task3: {
        count: 56
        time: 1050
      }
    },
    project25: {
      task7: {
        count: 25
        time: 10
      }
    }
  }
}

无论“项目”级别如何,我都想获取“task7”显示的详细信息。像下面这样,可能吗?

db.logins.find({tasks.*.task7.count}) 

标签: mongodbmongodb-queryaggregation-framework

解决方案


由于您的字段名称是动态的并且您无法列出所有动态键:

{ "tasks.project1.task7.count": 1, "tasks.project2.task7.count": 1,  "tasks.project25.task7.count": 1 }

而是尝试以下使用 MongoDB 的本机聚合管道的查询:

db.collection.aggregate([
    /** Convert `tasks` object into an array ([{k:...,v:...},{k:...,v:...}]) - here we're projecting only `tasks` field */
    {
      $project: { _id: 0, tasks: { $objectToArray: "$tasks" } }
    },
    /** Iterate over tasks array & re-shaping objects inside tasks & forming a new array of [{k:...,v:...},{k:...,v:...}]
     * We're using `arrayToObject` to convert array to object back again
     */
    {
      $project: {
        tasks: {
          $arrayToObject: { 
             $map: { input: "$tasks", in: { "k": "$$this.k", "v": { task7: { count: "$$this.v.task7.count" } } } } 
          }
        }
      }
    }
  ])

测试: mongoplayground

注意:我强烈建议避免在读取或更新现有文档时导致出现若干问题的动态字段名称。您将数据设计得非常好,并且应该采用这种方式 - 您将以首选方式编写一次并轻松阅读 n 次,否则如果您在编写时不相信更好的架构设计,那么您已经在每次读取时都执行这个繁琐的过程,这不是首选并且可能会很昂贵。


推荐阅读