单条件分组求和
mysql数据库
java代码此处就忽略了
类似mysql的失去了语句如下
select goodsName,sum(net)from weightingDataDetail group by goodsName
sql执行成功后返回的数据应该是
goodsName | net |
物料1 | 300 |
物料2 | 500 |
是可以直接映射到对象返回给前端直接渲染的。
mongoDB数据库
Java代码
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName")//设置分组字段
.sum("net").as("net"),
project("goodsName","net")
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
mongoDB这时候的sql为:
db.weightingDataDetail.aggregate(
[{
"$group": {
"_id":"$goodsName",
"net": {
"$sum": "$net"
}
}
}, {
"$project": {
"goodsName": "$_id.goodsName",
"net": 1,
}
}]
)
运行结果如下:
这时候映射到对象上物料在id上,这样前端是不能直接渲染,而且也不符合现实所需要的,但多条件分组时,就不会映射在id上了,很坑。
需要把mongDB的sql改为:
db.weightingDataDetail.aggregate(
[{
"$group": {
"_id": {
"goodsName": "$goodsName",
},
"net": {
"$sum": "$net"
}
}
}, {
"$project": {
"goodsName": "$_id.goodsName",
"net": 1,
}
}]
)
这时候运行结果就对了:
我一开始研究半天,怎么才能用java构建出
"_id": {
"goodsName": "$goodsName",
}这种条件。
这里使用"曲线救国"的方式实现
返回指定字段方式一
将"_id"起个别名,换成要返回的字段。
也就是
db.weightingDataDetail.aggregate(
[{
"$group": {
"_id": "$goodsName",
"net": {
"$sum": "$net"
}
}
}, {
"$project": {
"goodsName": "$_id",
"net": "$net"
}
}]
)
Java代码如下
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName")//设置分组字段
.sum("net").as("net"),
project("goodsName","net")
.andExpression("_id").as("goodsName") //将id起别名
.andExpression("net").as("net")
//或者这样起别名
.and("_id").as("goodsName")
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
起别名还可以使用previousOperation,一般配合and使用,这里就不展示sql了;官方解释:
选择n字段并为ID字段创建一个别名,该别名是由前一个组操作(因此调用previousOperation())生成的,其名称为标记。
java代码如下
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName")//设置分组字段
.sum("net").as("net"),
project("goodsName","net").and("goodsName").previousOperation()
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
返回指定字段方式二
将分组条件变为多条件,分组一个压根不存在的条件。
sql如下:
db.weightingDataDetail.aggregate(
[ {
"$group": {
"_id": {
"goodsName": "$goodsName",
"1": "$1"
},
"net": {
"$sum": "$net"
}
}
}, {
"$project": {
"goodsName": "$_id.goodsName",
"net": 1,
"1": "$_id.1"
}
}]
)
这样也是满足的,但是在mysql中这么做肯定是会报错的,不知道这个"1"是个啥。
java代码如下:
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName","1")//设置分组字段
.sum("net").as("net"),
project("goodsName","net")
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
返回指定字段方式三
可以使用$first和$last,前提是不适用sort的前提下,不适用排序,first和$last,会默认取出所有的,也会指定到返回的字段上。
$frist
返回将表达式应用到按键共享同一组文档的一组文档中的第一个文档所得到的值。仅在文档按定义的顺序排列时才有意义。
$last
返回将表达式应用于在一组按字段共享同一组文档的最后一个文档中得出的值。仅在文档按定义的 Sequences 排列时才有意义。
sql如下:
db.weightingDataDetail.aggregate(
[{
"$group": {
"_id": "$goodsName",
"net": {
"$sum": "$net"
},
"goodsName": {
"$first": "$goodsName" // "$last": "$goodsName"
}
}
}, {
"$project": {
"goodsName": 1,
"net": 1
}
}]
)
java代码如下:
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName")//设置分组字段
.sum("net").as("net")
.first("goodsName").as("goodsName"),
project("goodsName","net")
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
其实这三种方式我倾向第一种起别名。
返回指定字段特殊情况
多返回一个字段,前提是这个字段在分组条件里是唯一的,比如goodsName对应的orderType只有一种,不会出现一种goodsName有俩个orderType。
mysql sql如下
select goodsName,orderType,sum(net)from weightingDataDetail group by goodsName
值得注意的是mongo要像mysql这样返回分组以外的字段,这个字段必须在group条件下,才能作为返回条件。
可以使用返回指定字段方式三,不排序的情况下多加一种,也是可以的。
mongo sql如下,
db.weightingDataDetail.aggregate(
[{
"$group": {
"_id": "$goodsName",
"net": {
"$sum": "$net"
},
"orderType": {
"$first": "$orderType" // "$last": "$goodsName"
}
}
}, {
"$project": {
"goodsName": 1,
"net": 1,
"orderType":1
}
}]
)
结合一二种方式就可以返回指定的字段。
java代码如下
@Test
public void sum() {
Aggregation agg = null;
agg = Aggregation.newAggregation(
group("goodsName")//设置分组字段
.sum("net").as("net")
.first("orderType").as("orderType"),
project("goodsName","net","orderType")
.and("_id").as("goodsName")
.and("orderType").as("orderType")
);
AggregationResults<WeightingDataDetail> results = mongoTemplate.aggregate(agg,
"weightingDataDetail", WeightingDataDetail.class);
WeightingDataDetail weightingDataDetail = results.getMappedResults().get(0);
System.err.println(JSON.toJSONString(weightingDataDetail));
}
如上就是我遇到的坑,但感觉是有瑕疵的,如有更好的方式,欢迎加入我们群1074281704一起交流。