根据动态键对文档进行分组并将键转换为值

时间:2018-12-27 08:55:09

标签: python mongodb aggregation-framework pymongo

我在MongoDB中有一个数据,像这样的数据:

{
    "good": {
        "d1": 2,
        "d2": 56,
        "d3": 3
    },
    "school": {
        "d1": 4,
        "d3": 5,
        "d4": 12
    }
},
{
    "good": {
        "d5": 4,
        "d6": 5
    },
    "spark": {
        "d5": 6,
        "d6": 11,
        "d7": 10
    },
    "school": {
        "d5": 8,
        "d8": 7
    }
}

并且我想使用pymongo mapreduce生成这样的数据:

{
    'word': 'good',
    'info': [
        {
            'tbl_id': 'd1',
            'term_freq': 2
        },
        {
            'tbl_id': 'd2',
            'term_freq': 56
        },
        {
            'tbl_id': 'd3',
            'term_freq': 3
        },
        {
            'tbl_id': 'd5',
            'term_freq': 4
        },
        {
            'tbl_id': 'd6',
            'term_freq': 5
        }
    ]
}
{
    'word': 'school',
    'info': [
        {
            'tbl_id': 'd1',
            'term_freq': 4
        },
        {
            'tbl_id': 'd3',
            'term_freq': 5
        },
        {
            'tbl_id': 'd4',
            'term_freq': 12
        },
        {
            'tbl_id': 'd5',
            'term_freq': 8
        },
        {
            'tbl_id': 'd8',
            'term_freq': 7
        }
    ]
}
{
    'word': 'spark',
    'info': [
        {
            'tbl_id': 'd5',
            'term_freq': 6
        },
        {
            'tbl_id': 'd6',
            'term_freq': 11
        },
        {
            'tbl_id': 'd7',
            'term_freq': 10
        }
    ]
}

我该怎么办?还是有其他解决方案?

1 个答案:

答案 0 :(得分:1)

这里不需要* mapReduce`。聚合框架可以很好地处理此问题。

关于这是如何工作的,建议您看看documentation中的每个运算符。

_filter = {
    "input": {"$objectToArray": "$$ROOT"},
    "cond": {"$ne": ["$$this.k", "_id"]}
}

_map = {
    "$map": {
        "input": {"$filter": _filter},
        "in": {
            "k": "$$this.k",
            "info": {
                "$map": {
                    "input": {"$objectToArray": "$$this.v"},
                    "in": {"tbl_id": "$$this.k", "freq_term": "$$this.v"}
                }
            }
        }
    }
}

pipeline = [
    {"$project": {"word": _map}},
    {"$unwind": "$word"},
    {
        "$group": {
            "_id": "$word.k",
            "info": {
                "$push": "$word.info"
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "word": "$_id",
            "info": {
                "$reduce": {
                    "input": "$info",
                    "initialValue": [

                    ],
                    "in": {
                        "$concatArrays": [
                            "$$value",
                            "$$this"
                        ]
                    }
                }
            }
        }
    }
]

然后使用.aggregate()方法运行。

collection.aggregate(pipeline)