Python mongoengine从嵌入文档列表中获取值

Python mongoengine从嵌入文档列表中获取值,python,mongodb,mongodb-query,aggregation-framework,mongoengine,Python,Mongodb,Mongodb Query,Aggregation Framework,Mongoengine,给定几百个具有以下结构(如下)的文档,为特定参数x生成[date,value]列表的最佳方法是什么 {_id: ObjectId(...), date: 2014-12-04 21:25:43, values: [ { parameter: ObjectId(...), value: 34.5 }, { parameter: ObjectId(...), value: 1

给定几百个具有以下结构(如下)的文档,为特定参数x生成[date,value]列表的最佳方法是什么

 {_id: ObjectId(...),
    date: 2014-12-04 21:25:43,
    values: [
        {   parameter: ObjectId(...),
            value: 34.5
        },  
        {   parameter: ObjectId(...),
            value: 1.3
        }, 
        {   parameter: ObjectId(...),
            value: 2.0
        }, ...

    ]
}
以下是我目前的进展:

  • 获取包含特定参数的所有文档

    parameter = Parameter.objects.get_or_404(id = args.get('parameter'))
    data = Record.objects(values__parameter = parameter).all()
    
  • 转换为列表。这种方式似乎效率极低。如果有人有更好的方法,请告诉我

    list = [] 
    for i in data:
        for index, item in enumerate(i.values):
            if item['parameter'] == parameter:
                list.append({'date': i.date, 'value': item['value']})
    

  • 另一种方法是使用直接获取匹配参数:

    Record._get_collection().aggregate([
        { "$match": { "values.parameter": parameter } },
        { "$unwind": "$values" },
        { "$match": { "values.parameter": parameter } }
    ])
    
    或者,如果您能够:

    Record._get_collection().aggregate([
        { "$match": { "values.parameter": parameter } },
        { "$redact": {
            "$cond": [
                { "$eq": [{ "$ifNull": [ "$parameter", parameter ] }, parameter ] },
               "$$DESCEND",
               "$$PRUNE"
            ]
        }},
        { "$unwind": "$values" }  
    ])
    
    这两种方法都可以有效地将数组“反规范化”为单个文档,并“过滤”该列表,以便只处理匹配的元素。允许在取消规范化之前从数组中“修剪”元素,这节省了一点空间,通常比取消规范化不匹配的数组元素后进行过滤更有效

    如果希望在聚合管道的末尾添加一个,也可以将结果字段限制为所需的字段:

        { "$project": { "_id": 0, "date": 1, "value": "$values.value" } }
    
    这可能会为您节省一点从服务器传输回应用程序的内容,并消除在代码中操纵结果的需要


    \u get\u collection()
    有一种从底层pymongo驱动程序访问raw的非文档方式。这反过来又允许访问那里的方法。所有对象都是在普通列表中返回的普通python对象。

    另一种方法是使用直接获取匹配参数:

    Record._get_collection().aggregate([
        { "$match": { "values.parameter": parameter } },
        { "$unwind": "$values" },
        { "$match": { "values.parameter": parameter } }
    ])
    
    或者,如果您能够:

    Record._get_collection().aggregate([
        { "$match": { "values.parameter": parameter } },
        { "$redact": {
            "$cond": [
                { "$eq": [{ "$ifNull": [ "$parameter", parameter ] }, parameter ] },
               "$$DESCEND",
               "$$PRUNE"
            ]
        }},
        { "$unwind": "$values" }  
    ])
    
    这两种方法都可以有效地将数组“反规范化”为单个文档,并“过滤”该列表,以便只处理匹配的元素。允许在取消规范化之前从数组中“修剪”元素,这节省了一点空间,通常比取消规范化不匹配的数组元素后进行过滤更有效

    如果希望在聚合管道的末尾添加一个,也可以将结果字段限制为所需的字段:

        { "$project": { "_id": 0, "date": 1, "value": "$values.value" } }
    
    这可能会为您节省一点从服务器传输回应用程序的内容,并消除在代码中操纵结果的需要

    \u get\u collection()
    有一种从底层pymongo驱动程序访问raw的非文档方式。这反过来又允许访问那里的方法。所有对象都是在普通列表中返回的普通python对象