MongoDB查询内嵌数组(Spring中如何使用聚合查询)(2)

Srping集合MongoDB

地址:http://blog.csdn.net/bicheng4769/article/details/79626382

Spring中如何使用Aggregate聚合函数

  • 原始数据:
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "addTime" : ISODate("2018-03-16T03:05:04.363Z"),
    "tag" : "test",
    "userInfo" : [ { "name" : "cj", "address" : "江苏", "age" : 24.0, "userTag" : "stu" }, { "name" : "hj", "address" : "江苏", "age" : 26.0, "userTag" : "stu" }, { "name" : "lbl", "address" : "美国", "age" : 22.0, "userTag" : "teach" } ] }
  • 查询语句:
db.test.aggregate([{"$unwind":"$userInfo"},
{"$match":{"userInfo.userTag":"stu","tag":"test"}},
{"$project":{"userInfo":1}}])

方法一: 
ok,首先比较容易想到的方法是从上面的原生的查询语句中得到的。其实上面的写法我们可以换个如下:

db.getCollection('test').aggregate([{"$unwind":"$userInfo"},
{"$match":{"userInfo.userTag":"stu","tag":"test"}},
{"$project":{"userInfo":1}}])

这种写法的查询和上面的写法得到的结果是一样的,那么在spring-mongodb中是否有相似的写法呢?

mongoTemplate.getCollection(collectionName).aggregate(List<DBObject> pipeline);
  • 1

这很棒。下面我们需要做的就是构造一个List<DBObject>参数:

List<DBObject> dbObjects = new ArrayList<>();
DBObject condition = new BasicDBObject();
DBObject match = new BasicDBObject();
DBObject project = new BasicDBObject();
DBObject unwind = new BasicDBObject();
condition.put("tag", "test");
condition.put("userInfo.userTag", "stu");
match.put("$match", condition);
unwind.put("$unwind", "$userInfo");
project.put("$project", new BasicDBObject("userInfo", 1));

dbObjects.add(unwind);
dbObjects.add(match);
dbObjects.add(project);

所以最终查询方法如下:

mongoTemplate.getCollection("test").aggregate(dbObjects);

ok? 感觉好像少了点什么,结果呢?查询的结果在哪儿? 通过源码我们可以看到:

public AggregationOutput aggregate(List<DBObject> pipeline) {
        return this.aggregate(pipeline, this.getReadPreference());
}

这是返回一个AggregationOutput类,下面我们要做的就是从这个类中获取结果(不多说 给代码):

AggregationOutput output = mongoTemplate.getCollection("test").aggregate(dbObjects);
for (Iterator<DBObject> it = output.results().iterator(); it.hasNext(); ) {
            BasicDBObject dbo = (BasicDBObject) it.next();
            BasicDBObject dbo2 = (BasicDBObject) dbo.get("userInfo");
            String name= dbo2.get("name").toString();
            String address= dbo2.get("address").toString(); 
 }

附上完整代码;

List<DBObject> dbObjects = new ArrayList<>();
DBObject condition = new BasicDBObject();
DBObject match = new BasicDBObject();
DBObject project = new BasicDBObject();
DBObject unwind = new BasicDBObject();
condition.put("tag", "test");
condition.put("userInfo.userTag", "stu");
match.put("$match", condition);
unwind.put("$unwind", "$userInfo");
project.put("$project", new BasicDBObject("userInfo", 1));
dbObjects.add(unwind);
dbObjects.add(match);
dbObjects.add(project);
AggregationOutput output = mongoTemplate.getCollection("test").aggregate(dbObjects);
for (Iterator<DBObject> it = output.results().iterator(); it.hasNext(); ) {
            BasicDBObject dbo = (BasicDBObject) it.next();
            BasicDBObject dbo2 = (BasicDBObject) dbo.get("userInfo");
            String name= dbo2.get("name").toString();
            System.out.println(name);
            String address= dbo2.get("address").toString(); 
            System.out.println(address);
 }

方法二: 
既然spring-mongdb提供mongoTemplate这个类使用,那么我相信应该会有更加简便的方法使用,那么有没有呢?遇到这种问题,我们应该去官网查看 
https://docs.spring.io/spring-data/mongodb/docs/2.0.5.RELEASE/reference/html/#mongo.aggregation 
直接上代码:

Aggregation agg = newAggregation(
                unwind("$userInfo"),
                match(Criteria.where("tag").is("test").and("caseId").is(caseId).and("projectId").is(prjId).and("apmInfo.APMEnum").is(type)),
                project("apmInfo")
        );
AggregationResults<Object> results = mongoTemplate.aggregate(agg, "APMInfo", Object.class);
List<Object> resultList = results.getMappedResults();

很明显这种方法比第一种方法的代码量要少很多,推荐使用。

总结:

遇到问题时,我们先应该自己思考一下有没有什么合适的解决方案,然后再去官网寻找帮助,有文档看文档,尽量不要先去百度问题。 上述的第一种方法 虽然代码写的有点多,但其实跟原生的语句相差不大,理解比较容易,而且这种原生的方法不止针对aggregate函数,对于任何的原生的语句都可以实现。

相关文章
相关标签/搜索