MongoDB的聚合功能使用

来源:互联网 发布:mac os 哪个版本号 编辑:程序博客网 时间:2024/06/06 01:57
MongoDB的聚合功能的使用
        我在项目中主要使用的数据库是MongoDB,版本为2.4.6,目前最新的版本为3.0(还没有使用用,据说增加了很多新功能及改进)。
      很久以前完成了一个报表开发任务,用到了聚合,这里就简单的做了个记录,也分享给其他人。projectmonthdata表(习惯称集合为表)中保存了每个月份的项目冻结数据,我选选取了某条记录的部分字段值:
{
  "_id" : ObjectId("5339cfe7e0cca65106fa33e7"),
  "year" : 2014,
  "month" : 3,
  "date":1396281599999,
  "date" : NumberLong("1396281599999"),
  "project_id" : ObjectId("53391501e0cca65106f957d3"),
  "org_id":ObjectId(525ded94ede0a8ee8c1ca6dd),
  "month_investment_allocated" : 135.0,
  "month_investment_designated" : 11.0,
  "month_investment" : 146.0,
  "month_sales_cost" : 50.0,
  "month_sales_revenue" : 100.0,
  "month_sales_profit" : 50.0
}
        其中project_id对应了project表里面的_id,org_id对应了organization表里面的_id,month_investment_allocated是项目的部门投入费用,month_investment_designated是项目的研发投入费用,month_investment是项目的总费用,month_sales_cost是销售支出费用,month_sales_revenue是销售收益,month_sales_profit是销售利润,year是哪一年,month是哪个月,date是时间转换成的long格式。
        需求如下:界面上查询报表是可以选择某几个月的,需要将同一个项目不同月份的6中费用累加求和,聚合为一条数据。其中month_investment_allocated,month_investment_designated,month_investment相加小于0则这条记录不参与聚合(这里需求我都简化了,实际开发比这个复杂,因为主要只看聚合部分)。
mongodb的collection有个方法是aggregate如下:aggregate(query,group),第一个参数query是查询的限制条件,也就是查询符合哪些条件的数据,后面的参数group是可以有多个的,作为聚合分组。实际代码如下;
//这是第一个参数,也就是条件
DBObject match = new BasicDBObject().append(
"$match",
new BasicDBObject()
.append("$or", queryCostOrSales)
.append("date",
new BasicDBObject().append("$gt",
startDate.getTime()).append(
"$lte", endDate.getTime()))
.append(Project.F_FUNCTION_ORGANIZATION,
new BasicDBObject().append("$in",
orgIds)));
这里用json表示出来是这样的:{"$match":{{"$or“:[month_investment_allocated:{"$gt",0},
month_investment_designated:{"$gt",0},
month_investment:{"$gt",0}]},
{date:{"$gt":输入的开始时间,"$lte":"输入的结束时间"}},{org_id:{"$in":[输入的组织id数组]}}}}
表示的意思为:match去匹配month_investment_allocated、month_investment_designated、month_investment这三个值,值要大于0,紧接着要筛选出表中date字段的值要大于给定的输入时间,小于等于给定的结束时间,后面还有一个限制条件表中的org_id字段的值是给定的org_id的数组。


//这是第二个参数,也就是分组,多个的我还没用过
DBObject group = new BasicDBObject()
.append("$group",
new BasicDBObject()
.append("_id",
"$"
+ ProjectMonthData.F_PROJECTID)
.append(IProjectETL.F_INVESTMENT_ALLOCATED,
new BasicDBObject()
.append("$sum",
"$month_investment_allocated"))
.append(IProjectETL.F_INVESTMENT_DESIGNATED,
new BasicDBObject()
.append("$sum",
"$month_investment_designated"))
.append(IProjectETL.F_INVESTMENT,
new BasicDBObject().append(
"$sum",
"$month_investment"))
.append(IProjectETL.F_SALES_COST,
new BasicDBObject().append(
"$sum",
"$month_sales_cost"))
.append(IProjectETL.F_SALES_REVENUE,
new BasicDBObject().append(
"$sum",
"$month_sales_revenue"))
.append("sales_profit",
new BasicDBObject().append(
"$sum",
"$month_sales_profit")));
      这里我就不写json格式的了。
      然后把这两个参数传入到目标方法aggregate中,AggregationOutput aggregate = prjmd.aggregate(match, group);
      Iterator<DBObject> iter = aggregate.results().iterator();
这个itera中的DBObject类型的数据就是聚合出来的每一条新数据,然后遍历取出里面费用和_id,重新组合成新对象,就可以了。
      详细的下次会解释。
1 0