MongoDB:如果存在属性,则获取数组的最后一个元素

时间:2019-07-10 18:04:57

标签: mongodb aggregation-framework

我想将最后一个设置与现有值进行汇总。

我的数据结构:

{
  _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: [{}]settings.values: {}是解决方案的关键。然后,我可以project的单个值,使用$reverseArray$arrayElemAt: [$array, 0]来获取最后一个元素。

1 个答案:

答案 0 :(得分:1)

由于文档指出,您可以利用$mergeObjects运算符:

  

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

由于具有嵌套数组,因此需要双$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
        }
    }
])

Mongo Playground