访问数组

时间:2016-05-18 16:17:47

标签: mongodb pymongo aggregation-framework

考虑一个包含嵌入文档数组的文档:

{'array': [{'key1': 120.0, 'key2': 69.0}, {'key1': 100.0, 'key2': 50.0}]}

我想将key2投射到数组的第一个元素。

我天真地试过

'$project':
    {
        'item': '$array.0.key2'
    }

失败了(但解释了我想做的比许多单词更好)。

使用$ arrayElemAt和$ let

从MongoDB 3.2开始,可以使用$arrayElemAt从列表中获取项目:

'$project':
    {
        'item1': {'$arrayElemAt': ['$array', 0] }
    }

item1作为{'key1': 120.0, 'key2': 69.0}返回。

我想要key2

我设法使用$let

'$project':
    {
        'item': {
            '$let': {
                'vars': {
                    'tmp': {'$arrayElemAt': ['$array', 0] },
                    },
                'in': '$$tmp.key2'
            }
        },
    }

有更简单的方法吗?

这看起来很痛苦。特别是考虑到我想在几个表达式中使用这种结构来获得相同的值(测试不为零,然后在除法中使用)。

上下文

数组存储文档中表示的对象的连续状态,按日期,反向顺序排序。数组的第一个元素是最后一个(因此是当前的)状态。我想使用当前状态中两个值的比率对文档进行排序。

唯一合理的解决方案可能是将最后一个状态从数组中取出。或者甚至预先计算比率并对预先计算的值进行排序。

2 个答案:

答案 0 :(得分:2)

实际上,您不需要使用$let运算符来执行此操作。只需使用$arrayElemAt阶段中的$project运算符即可返回"数组中的第一项"和$$ROOT系统变量返回当前文档。在那里,您可以使用$sort轻松指定dot notation字段。此外,您可以向管道添加另一个$project阶段以丢弃"项目"字段和" _id"来自查询结果的字段。

db.collection.aggregate([
    { "$project": { 
        "item": { "$arrayElemAt": [ "$array", 0 ] },  
        "doc": "$$ROOT"
    }}, 
    { "$sort": { "item.key2": 1 } }, 
    { "$project": { "doc": 1, "_id": 0 } }
])

答案 1 :(得分:1)

在聚合管道中,您可以重复以下步骤以保持清洁:

'$project': {'item1': {'$arrayElemAt': ['$array', 0] }}

你可以添加:

{$project: {"item1.key2": 1}}