【问题标题】:MongoDB : not able to get the field 'name' which has the max value in the two similar sub-documentsMongoDB:无法获取两个相似子文档中具有最大值的字段“名称”
【发布时间】:2020-04-28 23:25:25
【问题描述】:

我有一个test 收藏:

{
    "_id" : ObjectId("5exxxxxx03"),
    "username" : "abc",
    "col1" : [
        {
            "colId" : 1
            "col2" : [
                {
                    "name" : "a",
                    "value" : 10
                },
                {
                    "name" : "b",
                    "value" : 20
                },
                {
                   "name" : "c",
                   "value" : 30
                }
            ],
            "col3" : [
                {
                    "name" : "d",
                    "value" : 15
                },
                {
                    "name" : "e",
                    "value" : 25
                },
                {
                    "name" : "f",
                    "value" : 35
                }
            ]
        }
    ]
}

col1 具有子文档col2col3 的列表,它们相似,但传达的含义不同。这两个子文档具有namevalue 作为字段。

现在,我需要从col2col3 及其对应的name 中找到最大的value

我尝试了以下查询:

db.test.aggregate([
    {$unwind: '$col1'},
    {$unwind: '$col1.col2'},
    {$unwind: '$col1.col3'},
    {$group:
        {_id: '$col1.colId',
        maxCol2: {$max: '$col1.col2.value'},
        maxCol3: {$max: '$col1.col3.value'}}},
    {$project:
        {maxValue: {$max: ['$maxCol2', '$maxCol3']},
        name: {$cond: [
            {$eq: ['$maxValue', '$maxCol2']},
            '$col1.col2.name',
            '$col1.col3.name']}}}]).pretty()

但是,结果如下,其中没有 name 字段:

{ "_id" : 1, "maxValue" : 35 }

所以,为了检查一下我的情况是否正确,请尝试以下查询($col1.col2.name$col1.col3.name 替换为 111222 字符串):

db.test.aggregate([
    {$unwind: '$col1'},
    {$unwind: '$col1.col2'},
    {$unwind: '$col1.col3'},
    {$group:
        {_id: '$col1.colId',
        maxCol2: {$max: '$col1.col2.value'},
        maxCol3: {$max: '$col1.col3.value'}}},
    {$project:
        {maxValue: {$max: ['$maxCol2', '$maxCol3']},
        name: {$cond: [
            {$eq: ['$maxValue', '$maxCol2']},
            '111',
            '222']}}}]).pretty()

这给了我预期的输出:

{ "_id" : 1, "maxValue" : 35, "name" : "222" }

谁能指导我为什么我没有得到正确的答案,我应该如何查询这个以获得正确的输出?

正确的输出应该是:

{ "_id" : 1, "maxValue" : 35, "name" : "f" }

附: - 我是初学者。

【问题讨论】:

  • 您可以尝试使用 $addFields 之类的方法来执行条件映射并从 $project 中删除条件。此外,如果您使用的不是最新的服务器版本,请尝试升级。
  • @ngShavil.py :如果col1 数组中有多个对象怎么办?使用 "colId" : 1"colId" : 2"colId" : 3... 你想为 col1 中的每个单独对象获得最大还是为所有 "colId" : 1"colId" : 2"colId" : 3 组合获得最大?
  • @whoami,我想为col1 中的每个单独对象获得最大的。
  • @Oleg,谢谢,我会试试的。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

你可以使用下面的聚合

db.collection.aggregate([
  { "$project": {
    "col1": {
      "$max": {
        "$reduce": {
          "input": "$col1",
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$this.col2",
              "$$value",
              "$$this.col3"
            ]
          }
        }
      }
    }
  }}
])

MongoPlayground

【讨论】:

  • 谢谢!它有效,但我正在寻找类似于我的查询的东西。 PS - 我是初学者。
  • 你能分开解释每个阶段吗?现在它太冗长了
  • @KunalMukherjee $reduce 用于展平嵌套数组。 $max 从展平数组中获取最大值。您可以通过从查询中删除运算符来一一检查。
【解决方案2】:

试试这个:

说明

我们需要添加带有col2col3 值的额外字段。一旦我们计算出最大值,我们就会根据最大值检索名称。


db.collection.aggregate([
  {
    $unwind: "$col1"
  },
  {
    $unwind: "$col1.col2"
  },
  {
    $unwind: "$col1.col3"
  },
  {
    $group: {
      _id: "$col1.colId",
      maxCol2: {
        $max: "$col1.col2.value"
      },
      maxCol3: {
        $max: "$col1.col3.value"
      },
      col2: {
        $addToSet: "$col1.col2"
      },
      col3: {
        $addToSet: "$col1.col3"
      }
    }
  },
  {
    $project: {
      maxValue: {
        $filter: {
          input: {
            $cond: [
              {
                $gt: [
                  "$maxCol2",
                  "$maxCol3"
                ]
              },
              "$col2",
              "$col3"
            ]
          },
          cond: {
            $eq: [
              "$$this.value",
              {
                $cond: [
                  {
                    $gt: [
                      "$maxCol2",
                      "$maxCol3"
                    ]
                  },
                  "$maxCol2",
                  "$maxCol3"
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $unwind: "$maxValue"
  },
  {
    $project: {
      _id: 1,
      maxValue: "$maxValue.value",
      name: "$maxValue.name"
    }
  }
])

MongoPlayground | Merging col2 / col3 | Per document

【讨论】:

  • 实际上,您的查询给出了准确的输出,与我的预期输出相匹配。但是,是否可以对我的查询进行任何细微的修改以获得所需的输出?
  • @ngShravil.py 检查this。这就是我们需要调整您的解决方案以获得所需结果的方式
  • 你想用这个查询更新答案吗?
  • @ngShravil.py 完成。谢谢
  • 我稍微修改了查询,maxValuename 字段互换了。
猜你喜欢
  • 2020-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多