5

是直接的,我如何做到這一點:聚集項目組通過提取日,月,年和Spring數據

group._id = { 
    year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
    month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
    day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] } 
}; 

彈簧數據

我想這已經和其他一些形式和人不是全成

Aggregation aggregation = Aggregation.newAggregation(
       Aggregation.match(c), 
       Aggregation.project("programa", "custo", "duracao", "dataHora") 
        .andExpression("dataHora").minus(25200000).extractDayOfMonth().as("dia") 
        .andExpression("dataHora").minus(25200000).extractMonth().as("mes") 
        .andExpression("dataHora").minus(25200000).extractYear().as("ano"), 
       Aggregation.group("programa", "ano", "mes", "dia") 
        .count().as("count") 
        .sum("custo").as("valorTotal") 
        .sum("duracao").as("duracaoTotal") 
        .first("dataHora").as("dataHora"), 
       Aggregation.sort(Direction.ASC, "dataHora") 
     ); 

我需要按天,月和年在MongoDB中,否則我將需要所有這些分組的數據轉換成代碼。

在此先感謝

回答

5

您正在運行到春天蒙戈的,你可以在一個單一的$project階段場計算做什麼限制,而事實上你很可能已經編寫爲一個單獨的$project,因爲你會發現你目前無法直接在$group_id中投影自定義命名字段。

所以你會更好斷保持這一切都在$group,以及使用四捨五入的調整日期以本地時間的不同方法。

更好的方式來寫你因此$group是:

{ "$group": { 
    "_id": { 
    "programa": "$programa", 
    "dataHora": { 
     "$add": [ 
     { "$subtract": [ 
      { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] }, 
      { "$mod": [ 
      { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] }, 
      1000 * 60 * 60 * 24 
      ]} 
     ]}, 
     new Date(0) 
     ] 
    } 
    }, 
    "count": { "$sum": 1 }, 
    "valorTotal": { "$sum": "$custo" }, 
    "duracaoTotal": { "$sum": "$duracao" }, 
    "dataHora": { "$first": "$dataHora" } 
}} 

過程中使用這種與結構的彈簧蒙戈您需要的聚合階段操作的自定義實現,可以採取一個定義DBObject

public class CustomGroupOperation implements AggregationOperation { 
    private DBObject operation; 

    public CustomGroupOperation (DBObject operation) { 
     this.operation = operation; 
    } 

    @Override 
    public DBObject toDBObject(AggregationOperationContext context) { 
     return context.getMappedObject(operation); 
    } 
} 

你那麼環境中使用這樣的:

Aggregation aggregation = Aggregation.newAggregation(
      Aggregation.match(c), 
      new CustomGroupOperation(
       new BasicDBObject("$group", 
        new BasicDBObject("_id", 
         new BasicDBObject("programa","$programa") 
          .append("dataHora", 
           new BasicDBObject("$add",Arrays.asList(
            new BasicDBObject("$subtract",Arrays.asList(
             new BasicDBObject("$subtract",Arrays.asList(
              new BasicDBObject("$subtract",Arrays.asList(
               "$dataHora", new Date(0) 
              )), 
              25200000 
             )), 
             new BasicDBObject("$mod",Arrays.asList(
              new BasicDBObject("$subtract",Arrays.asList(
               new BasicDBObject("$subtract",Arrays.asList(
                "$dataHora", new Date(0) 
               )), 
               25200000 
              )), 
              1000 * 60 * 60 * 24 
             )) 
            )), 
            new Date(0) 
           )) 
          ) 
        ) 
        .append("count",new BasicDBObject("$sum",1)) 
        .append("valorTotal",new BasicDBObject("$sum","$custo")) 
        .append("duracaoTotal",new BasicDBObject("$sum","$duracao")) 
        .append("dataHora",new BasicDBObject("$first","$dataHora")) 
       ) 
      ), 
      Aggregation.sort(Direction.ASC,"_id.dataHora") 
    ); 

由於通過內置的輔助方法,使用相同的基本類的自定義類摘要,它可以和他們一起使用,如圖所示。

如何使用日期數學的基本過程在這裏工作的是,當您從一個BSON Date對象$subtract結果是毫秒的差異,在這種情況下從紀元日期(日期(0))只是提取毫秒值。這允許你做數學題,通過毫秒數模($mod)舍入到當前的日期值在一天。

就像你最初試過的那樣,當你接着$add那毫秒值到一個BSON Date對象時,返回值又是一個BSON Date。因此,向代表曆元的對象添加一個新的Date對象,但四捨五入到當前日期。

這通常比通過date aggregation operators提取部件更有用,而且對代碼的處理時間稍短一些,特別是根據您在此處調整UTC的時間時。

雖然這裏的$group的敷設渠道是有點比春天蒙戈的輔助功能正試圖避免更簡潔,它到底比運行單獨的$project階段轉變的字段值很多更有效,你無論如何,真的只想在$group階段。

+0

非常感謝您的回答,並感謝您花這一次來解釋mongo限制和解決方法!我會嘗試這種方法 – Thiesen

+0

這個答案很有用! – nurgasemetey

相關問題