【问题标题】:Aggregation query in mongo and spring-data-mongomongo 和 spring-data-mongo 中的聚合查询
【发布时间】:2017-05-02 11:06:07
【问题描述】:

大家好,我在查询数据时遇到了一个大问题。我有这样的文件:

{
    "_id" : NumberLong(999789748357864),
    "text" : "#asd #weila #asd2 welcome in my house",
    "date" : ISODate("2016-12-13T21:44:37.000Z"),
    "dateString" : "2016-12-13",
    "hashtags" : [ 
        "asd", 
        "weila", 
        "asd2"
    ]
}

我想构建两个查询:

1) 计算每天标签的数量,然后退出,例如:

{_id:"2016-12-13",
hashtags:[
{hashtag:"asd",count:20},
{hashtag:"weila",count:18},
{hashtag:"asd2",count:10},
....
]
}

{_id:"2016-12-14",
hashtags:[
{hashtag:"asd",count:18},
{hashtag:"asd2",count:14},
{hashtag:"weila",count:10},
....
]
}

2)另一个是相同的,但我想设置一个从 2016-12-13 到 2016-12-17 的时间段。

对于第一个查询,我编写了此查询并得到了搜索结果,但在 Spring Data Mongo 中我不知道如何编写。

db.comment.aggregate([
{$unwind:"$hashtags"},
{"$group":{
    "_id":{ 
        "date" : "$dateString",
        "hashtag": "$hashtags"
    },
    "count":{"$sum":1}
    }
},
{"$group":{
    "_id": "$_id.date",
    "hashtags": { 
       "$push": { 
       "hashtag": "$_id.hashtag",
       "count": "$count"
     }},
     "count": { "$sum": "$count" }
}},
{"$sort": { count: -1}},
{"$unwind": "$hashtags"},
{"$sort": { "count": -1, "hashtags.count": -1}},
{"$group": {
        "_id": "$_id",
        "hashtags": { "$push": "$hashtags" },
        "count": { "$first": "$count" }
    }},
{$project:{name:1,hashtags: { $slice: ["$hashtags", 2 ]}}}
]);

【问题讨论】:

    标签: mongodb mongodb-query spring-data aggregation-framework spring-data-mongodb


    【解决方案1】:

    在第二组阶段之后,您仍然可以使用相同聚合操作的一部分减去管道步骤,但对于过滤方面,您必须在初始 $match 中引入日期范围查询> 管道步骤。

    以下 mongo shell 示例 展示您如何过滤特定日期范围的聚合:

    1) 设置一个从 2016-12-13 到 2016-12-14 的时间段:

    var startDate = new Date("2016-12-13");
    startDate.setHours(0,0,0,0);
    
    var endDate = new Date("2016-12-14");
    endDate.setHours(23,59,59,999);
    var pipeline = [
        { 
            "$match": {
                "date": { "$gte": startDate, "$lte": endDate }
            }
        }
        { "$unwind": "$hashtags" },
        {
            "$group": {
                "_id": {
                    "date": "$dateString",
                    "hashtag": "$hashtags"
                },
                "count": { "$sum": 1 }
            }
        },
        {
            "$group": {
                "_id": "$_id.date",
                "hashtags": { 
                    "$push": { 
                        "hashtag": "$_id.hashtag",
                        "count": "$count"
                    }
                }
            }
        }
    ]
    db.comment.aggregate(pipeline)
    

    2) 设置一个从 2016-12-13 到 2016-12-17 的时间段:

    var startDate = new Date("2016-12-13");
    startDate.setHours(0,0,0,0);
    
    var endDate = new Date("2016-12-17");
    endDate.setHours(23,59,59,999);
    // run the same pipeline as above but with the date range query set as required
    

    Spring 数据等效项(未经测试):

    import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
    
    Aggregation agg = newAggregation(
        match(Criteria.where("date").gte(startDate).lte(endDate)),
        unwind("hashtags"),
        group("dateString", "hashtags").count().as("count"),
        group("_id.dateString")
            .push(new BasicDBObject
                ("hashtag", "$_id.hashtags").append
                ("count", "$count")
            ).as("hashtags") 
    );
    AggregationResults<Comment> results = mongoTemplate.aggregate(agg, Comment.class); 
    List<Comment> comments = results.getMappedResults();
    

    【讨论】:

    • 感谢您的回答@chridam,我意识到同样的事情并且运行良好,但是使用此解决方案我必须每天进行一次查询。在案例 2 中,它是完美的。你知道如何在 Spring Data 中对 hashtag 数组进行切片以仅获取前十个元素吗?在 mongo 中,我对计数进行排序,然后执行 projection{$project:{name:1,hashtags: { $slice: ["$hashtags", 2 ]}}},但我使用的版本没有实现 $slice。我需要对内部结构进行排序并对其进行限制,但是在 Spring Data mongo 中我不知道该怎么做,有什么建议吗?
    • 在聚合查询的组后面添加这个project("name").and("hashtags").project("slice", 2))
    • 谢谢@SagarReddy,我以一种奇怪的方式解决了这个问题,但结果是正确的。我在聚合函数的第二组步骤之前放了一个限制(2),但我会用你建议的那个来改变这个指令;)
    猜你喜欢
    • 1970-01-01
    • 2019-10-14
    • 2020-04-29
    • 2019-11-27
    • 1970-01-01
    • 2022-01-17
    • 2023-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多