【问题标题】:Mongodb select all fields group by one field and sort by another fieldMongodb选择所有字段按一个字段分组并按另一个字段排序
【发布时间】:2014-06-23 01:00:00
【问题描述】:

我们收集了包含以下字段的“消息”

_id |   messageId |  chainId | createOn

1   |       1     |    A     | 155
2   |       2     |    A     | 185
3   |       3     |    A     | 225
4   |       4     |    B     | 226
5   |       5     |    C     | 228
6   |       6     |    B     | 300

我们要选择具有以下条件的文档的所有字段

  1. 按字段 'chainId' 区分
  2. order(sort) by 'createdOn' in desc order

所以,预期的结果是

_id |   messageId |  chainId | createOn

3   |       3     |    A     | 225
5   |       5     |    C     | 228
6   |       6     |    B     | 300

我们在 java 应用程序中使用 spring-data。我尝试采用不同的方法,到目前为止没有任何帮助。
是否可以通过单个查询实现上述目标?

【问题讨论】:

    标签: java mongodb mapreduce aggregation-framework spring-data-mongodb


    【解决方案1】:

    您想要的是可以通过聚合框架实现的东西。 (对别人有用)的基本形式是:

    db.collection.aggregate([
    
        // Group by the grouping key, but keep the valid values
        { "$group": {
            "_id": "$chainId",
            "docId": { "$first": "$_id" },
            "messageId": { "$first": "$messageId" },
            "createOn": { "$first": "$createdOn" }
        }},
    
        // Then sort
        { "$sort": { "createOn": -1 } }
    
    ])
    

    以便在“messageId”的不同值上“分组”,同时为每个其他字段获取$first 边界值。或者,如果您想要最大的,则使用$last,但对于最小或最大的行,首先使用$sort 可能是有意义的,否则如果整行不重要,请使用$min$max

    有关使用的更多信息,请参阅 MongoDB aggregate() 文档,以及有关聚合方法和可能的帮助程序的更多使用的驱动程序 JavaDocs 和 SpringData Mongo 连接器文档。

    【讨论】:

    • 谢谢。它也帮助了我。干杯!!
    【解决方案2】:

    这里是使用 MongoDB Java Driver 的解决方案

        final MongoClient mongoClient = new MongoClient();
        final DB db = mongoClient.getDB("mstreettest");
        final DBCollection collection = db.getCollection("message");
    
        final BasicDBObject groupFields = new BasicDBObject("_id", "$chainId");
        groupFields.put("docId", new BasicDBObject("$first", "$_id"));
        groupFields.put("messageId", new BasicDBObject("$first", "$messageId"));
        groupFields.put("createOn", new BasicDBObject("$first", "$createdOn"));
    
        final DBObject group = new BasicDBObject("$group", groupFields);
    
        final DBObject sortFields = new BasicDBObject("createOn", -1);
        final DBObject sort = new BasicDBObject("$sort", sortFields);
    
        final DBObject projectFields = new BasicDBObject("_id", 0);
        projectFields.put("_id", "$docId");
        projectFields.put("messageId", "$messageId");
        projectFields.put("chainId", "$_id");
        projectFields.put("createOn", "$createOn");
        final DBObject project = new BasicDBObject("$project", projectFields);
    
        final AggregationOutput aggregate = collection.aggregate(group, sort, project);
    

    结果将是:

    { "_id" : 5 , "messageId" : 5 , "createOn" : { "$date" : "2014-04-23T04:45:45.173Z"} , "chainId" : "C"}
    { "_id" : 4 , "messageId" : 4 , "createOn" : { "$date" : "2014-04-23T04:12:25.173Z"} , "chainId" : "B"}
    { "_id" : 1 , "messageId" : 1 , "createOn" : { "$date" : "2014-04-22T08:29:05.173Z"} , "chainId" : "A"}
    

    我用 SpringData Mongo 尝试过,当我按 chainId(java.lang.NumberFormatException: For input string: "C") 分组时它不起作用

    【讨论】:

      【解决方案3】:

      替换这一行:

      final DBObject group = new BasicDBObject("$group", groupFields);
      

      用这个:

      final DBObject group = new BasicDBObject("_id", groupFields);
      

      【讨论】:

        【解决方案4】:

        这里是使用 springframework.data.mongodb 的解决方案:

        Aggregation aggregation = Aggregation.newAggregation(
                        Aggregation.group("chainId"),
                        Aggregation.sort(new Sort(Sort.Direction.ASC, "createdOn"))
                      );
        AggregationResults<XxxBean> results = mongoTemplate.aggregate(aggregation, "collection_name", XxxBean.class);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多