Mongo:对热门流量关键字进行分组

时间:2013-11-25 19:27:37

标签: mongodb aggregation-framework

我有一组共享以下格式的mongo文档(每天都是另一个):

{
    "query" : {
        "start-date" : ISODate("2013-11-24T00:00:00Z"),
        "end-date" : ISODate("2013-11-24T00:00:00Z"),
        "dimensions" : "ga:keyword",
        "metrics" : [
            "ga:organicSearches"
        ],
    },
    "totalResults" : 3,
    "totalsForAllResults" : {
        "ga:organicSearches" : 22
    },
    "rows" : [
        [
            "Paradise",
            18
        ],
        [
            "vacations",
            1
        ],
        [
            "vacation rentals",
            3
        ]
    ],
    "query_id" : 1,
}

因此,每天(开始日期)可以包含相同或不同(行)的关键字和值。

{
    "query" : {
        "start-date" : ISODate("2013-11-25T00:00:00Z"),
        "end-date" : ISODate("2013-11-25T00:00:00Z"),
        "dimensions" : "ga:keyword",
        "metrics" : [
            "ga:organicSearches"
        ],
    },
    "totalResults" : 3,
    "totalsForAllResults" : {
        "ga:organicSearches" : 22
    },
    "rows" : [
        [
            "paradise",
            20
        ],
        [
            "vacations",
            3
        ],
        [
            "relax is monday",
            8
        ]
    ],
    "query_id" : 1,
}

我正在阅读很多关于放松,比赛,分组和排序的内容。老实说,我离寻找一个优雅的解决方案太远了。

使用聚合框架:我想知道如何在任何特定日期范围内获得最高流量关键字(关键字和关键字数量可能会在一天之间变化)?

提前致谢。

1 个答案:

答案 0 :(得分:2)

使用这样的模式很难找到整洁的解决方案。使用聚合框架时,您无法通过索引访问数组元素,因此您必须放松两次以访问单个关键字和计数。您可以尝试使用与此类似的管道:

pipeline = [
    // Filter by date
    {
        "$match" : {
            "query.start-date" : {
                "$gte" : ISODate("2010-01-01T00:00:00Z")
            },
            "query.end-date" : {
                "$lte" : ISODate("2014-01-01T00:00:00Z")
            }
        }
    },
    // Unwind rows array 
    {
        "$unwind" : "$rows"
    },
    // Keep keyword-count as a key for second unwind
    {
        "$project" : {
            "rows" : 1,
            "keyword" : "$rows"
        }
    },
    // Unwind once again to get count and keyword document
    {
        "$unwind" : "$rows"
    },
    // I am not sure it is required but to be sure we sort documents
    {
        "$sort" : {
            "_id" : 1,
            "keyword" : 1,
            "rows" : -1
        }
    },
    // Group to extract keyword-count pairs
    {
        "$group" : {
            "_id" : {
                "i" : "$id",
                "k" : "$keyword"
            },
            "keyword" : {
                "$first" : "$rows"
            },
            "count" : {
                "$last" : "$rows"
            }
        }
    },
    // Final grouping
    {
        "$group" : {
            "_id" : "$keyword",
            "count" : {
                "$sum" : "$count"
            }
        }
    }
]
db.foo.aggregate(pipeline)