Java连接mongoDB聚合分组查询返回指定参数存在的一些问题

单条件分组求和

mysql数据库

java代码此处就忽略了

类似mysql的失去了语句如下

select goodsName,sum(net)from weightingDataDetail group by goodsName

sql执行成功后返回的数据应该是

goodsNamenet
物料1300
物料2500

是可以直接映射到对象返回给前端直接渲染的。

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一起交流。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java 中操作 MongoDB 进行聚合查询可以使用 MongoDBJava 驱动程序。下面是一个简单的示例代码,它演示了如何使用 Java 驱动程序执行 MongoDB 聚合查询: ```java import com.mongodb.MongoClient; import com.mongodb.client.AggregateIterable; import com.mongodb.client.MongoDatabase; import org.bson.Document; import java.util.Arrays; public class MongoDBAggregationExample { public static void main(String[] args) { // 创建 MongoDB 客户端 MongoClient mongoClient = new MongoClient("localhost", 27017); // 获取数据库 MongoDatabase database = mongoClient.getDatabase("test"); // 执行聚合查询 AggregateIterable<Document> result = database.getCollection("sales").aggregate(Arrays.asList( new Document("$group", new Document("_id", "$product").append("total", new Document("$sum", "$quantity"))), new Document("$sort", new Document("total", -1)) )); // 打印结果 for (Document doc : result) { System.out.println(doc.toJson()); } // 关闭客户端 mongoClient.close(); } } ``` 在这个示例中,我们创建了一个 `MongoClient` 对象来连接 MongoDB 数据库。然后,我们获取了 `test` 数据库,并对 `sales` 集合执行了一个聚合查询。这个聚合查询使用了 `$group` 和 `$sum` 操作符来计算每个产品的总销量,并使用 `$sort` 操作符按降序排列结果。最后,我们遍历了查询结果并打印了每个文档的 JSON 表示。 需要注意的是,聚合查询返回的结果是一个 `AggregateIterable<Document>` 对象,可以通过迭代器来遍历结果集合。在遍历结果时,可以使用 `toJson()` 方法将每个文档转换为 JSON 格式的字符串,或者使用 `get()` 方法获取文档中的字段值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

答 案

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值