首页 > 解决方案 > MongoDB:如果属性存在,则获取数组的最后一个元素

问题描述

我想将最后一个设置与现有值聚合。

我的数据结构:

{
  _id: 1,
  ...(many other fields)...
  settings: [
    {
      _id: 11,
      values: [
        {
          likesFruit: true,
          likesMeat: true,
        }
      ] 
   },
   {
      _id: 12,
      values: [
        {
          likesFruit: false
        }
      ] 
    }
  ]
}, 
{
  _id: 2,
  ...(many other fields)...
  settings: [] // empty
}

问题:如何得到这个结果

{
  _id: 1,
  ...(many other fields)...
  likesFruit: false,
  likesMeat: true
},
{
 _id: 2,
 ...(many other fields)...
}

我需要一个解决方案,它不会删除设置为空/不包含所有道具的结果。例如_id: 2不包含任何设置。因此,我不想展开它并针对特定设置对其进行过滤,因为即使不存在设置,我仍然需要根对象。

我试过了addFields

$addFields: {
  likesFruit: "$settings.value.likesFruit",
  likesMeat: "$settings.value.likesMeat"
}

这让我有了这个:

_id: 1,
...(many other fields)...
settings: [...],
likesFruit: [[true], [false]]
likesMeat: [[], [true]]

我试图过滤:

$addFields: {
  likesFruit: {
    $filter: {
      input: "$likesMeat",
      as: "items",
      cond: { $ne : ["$$items", null ] }
    }
  }
}

我的主要问题是双重嵌套。我感兴趣的“settings.value”里面只有一个对象。所以我想从settings.values: [{}]tosettings.values: {}将是解决方案的关键。然后我可以project使用单个值$reverseArray$arrayElemAt: [$array, 0]获取最后一个元素。

标签: mongodbaggregation-framework

解决方案


您可以利用$mergeObjects运算符,因为正如文档所述:

mergeObjects 在合并文档时会覆盖字段值。如果要合并的文档包含相同的字段名称,则结果文档中的字段具有为该字段合并的最后一个文档的值。

由于您有嵌套数组,因此您需要使用 double $reduce来聚合数据。您还可以使用$replaceRoot将您的聚合值提升到顶层

db.col.aggregate([
    {
        $addFields: {
            settingsAggregated: {
                $reduce: {
                    input: "$settings",
                    initialValue: {},
                    in: {
                        $mergeObjects: [ "$$value", 
                            { $reduce: { input: "$$this.values", initialValue: {}, in: { $mergeObjects: [ "$$value", "$$this" ] } } }
                        ]
                    }
                }
            }
        }
    },
    {
        $replaceRoot: {
            newRoot: {
                $mergeObjects: [ "$$ROOT", "$settingsAggregated" ]
            }
        }
    },
    {
        $project: {
            settings: 0,
            settingsAggregated: 0
        }
    }
])

蒙戈游乐场


推荐阅读