首先列出所需部分数据
集合user:
/* 1 */{ "_id" : 1.0, "hire" : ISODate("2016-12-15T02:52:04.630Z")}/* 2 */{ "_id" : 2.0, "chinese" : 80.0, "math" : 90.0, "name" : "lisi"}/* 3 */{ "_id" : 3.0, "chinese" : 70.0, "math" : 90.0, "name" : "wangwu"}/* 4 */{ "_id" : 4.0, "name" : "zs", "chinese" : 50, "math" : 60}
集合date:
/* 1 */{ "_id" : 1, "hire" : ISODate("2016-12-20T08:37:15.705Z")}
集合mycol:
/* 1 */{ "_id" : ObjectId("57ec6d0d7fbbc90bccc18e13"), "title" : "MongoDB1", "description" : "nosql", "likes" : 0, "by_user" : "lzq"}/* 2 */{ "_id" : ObjectId("57ec6d0d7fbbc90bccc18e14"), "title" : "MongoDB2", "description" : "nosql", "likes" : 2, "by_user" : "lzq"}/* 3 */{ "_id" : ObjectId("57ec6d0d7fbbc90bccc18e15"), "title" : "MongoDB3", "description" : "nosql", "likes" : 3, "by_user" : "lzq"}
集合tree:
/* 1 */{ "_id" : ObjectId("584e47110dc763ff7e50347b"), "management" : { "organization" : [ { "name" : "Organizational institution", "index" : 1.0 }, { "name" : "Company files", "index" : 2.0 }, { "name" : "department files", "index" : 3.0 } ], "authority" : [ { "name" : "user", "sequence" : 100.0 }, { "name" : "role", "sequence" : 102.0 }, { "name" : { "source_register" : [ { "name" : "button" }, { "name" : "field" } ] }, "sequence" : 103.0 } ] }, "num" : 1.0}
Code:
聚合操作所有JSON定义类
package db.mongo.feature.util;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import java.util.Arrays;import java.util.List;public class AggregateJson{ //$project操作 public static final String USERPROJECT = "{$project:{\"userid\":\"$_id\",\"_id\":0}}"; //$project操作与$add操作(示例:perStuTotalScore) public static final String PROJECT_ADD = "{\n" + " $project:{\n" + " chinese:1,\n" + " math:1,\n" + " totalgrade:{$add:[\"$chinese\",\"$math\"]}\n" + " }\n" + " }"; //日期操作(示例date集合) public static final String DATE_EXPRESSION = "{\n" + " $project:\n" + " {\n" + " year: { $year: \"$hire\" },\n" + " month: { $month: \"$hire\" },\n" + " day: { $dayOfMonth: \"$hire\" },\n" + " hour: { $hour: \"$hire\" },\n" + " minutes: { $minute: \"$hire\" },\n" + " seconds: { $second: \"$hire\" },\n" + " milliseconds: { $millisecond: \"$hire\" },\n" + " dayOfYear: { $dayOfYear: \"$hire\" },\n" + " dayOfWeek: { $dayOfWeek: \"$hire\" },\n" + " week: { $week: \"$hire\" }\n" + " }\n" + " }"; //截取name的第一个字节,与.和$sex值拼接(示例mycol集合) public static final String[] PROJECT_CONCAT_SUBSTR = {"{$project:{\"title\":{\n" + " $concat:[\"$by_user\",\".\",{$substr:[\"$title\",5,8]}]\n" + " }}}","{$limit:2}"}; //比较两个数值大小(示例user集合) public static final String PROJECT_CMP = "{\n" + " $project:{\n" + " chinese:1,\n" + " math:1,\n" + " compareTo:{$cmp:[\"$chinese\",\"$math\"]}\n" + " }\n" + " }"; public static final String[] PRJECT_GROUP_SORT_LIMIT = {"{ \n" + " $project: {\n" + " \"name\": 1,\n" + " \"chinese\":1,\n" + " \"math\":1\n" + " }\n" + " }", "{ $group: { _id: \"$name\" ,totalScore:{$sum:{$add:[\"$chinese\",\"$math\"]}}} }", "{\n" + " $sort: {\n" + " \"totalScore\": -1\n" + " }\n" + " }", "{\n" + " $limit: 3\n" + " }"}; public static final String PROJECT_COND = "{\n" + " $project:\n" + " {\n" + " \n" + " discount:\n" + " {\n" + " $cond: { if: { $gte: [ \"$chinese\", 60 ] }, then: \"$chinese\", else: \"不合格\" }\n" + " }\n" + " }\n" + " }"; public static final String UNWIND = "{$unwind:\"$management.organization\"}"; public static final String DISTINCT = "{\"distinct\":\"user\",\"key\":\"chinese\"}";}
聚合操作类:
package db.mongo.feature;import com.mongodb.AggregationOptions;import com.mongodb.GroupCommand;import com.mongodb.MongoClient;import com.mongodb.client.*;import com.mongodb.client.model.Filters;import com.mongodb.client.model.FindOptions;import com.mongodb.client.model.Projections;import com.mongodb.client.model.Sorts;import com.mongodb.operation.GroupOperation;import db.mongo.feature.util.AggregateJson;import db.mongo.util.Constants;import org.apache.log4j.Logger;import org.bson.BsonDocument;import org.bson.Document;import org.bson.conversions.Bson;import org.junit.Before;import org.junit.Test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class MongoAggregate { /* 聚合:对集合中的文档进行变换和组合,可对文档进行一连串的处理. $match $project $group $unwind $limit $skip $sort... 需要将聚合操作传给aggregate,db.articles.aggregate如果不是从数据库返回的集合,那么Mongo Shell会自动迭代20次 MongoDB不允许管道占用很多内存,如20%,会直接报错*//*$project代表将articles集合投射出author字段,结果集中只包含_id和author字段; $match匹配以x开头的author; 然后"_id":"$author"指定了分组字段author; $group会在结果集中创建count字段,执行结果类似这样的结构:{ "_id" : "xiaobao", "count" : 10 }; $sort按照count字段将以上结果排序; $limit将限制返回结果集的前三个文档 "$filename"是为了引用字段的值*/ private static Logger logger = Logger.getLogger(MongoAggregate.class); MongoDatabase database = null; public MongoCollectiongetCollection(String collectionName) { return this.database.getCollection(collectionName); } @Before public void connect(){ MongoClient client = new MongoClient(Constants.MONGO_HOST,Constants.MONGO_PORT); //当前获取这个数据库时并没有这个名称的数据库,不会报错,当有数据添加的时候才会创建 database = client.getDatabase("test"); } /** * @param collection 接收一个指定的mongo集合 * @param jsons 接收json数组,用来聚合查询时解析多个json过滤条件 * * 接收多个json字符串 */ public void aggregate(MongoCollection collection,String... jsons){ List pileline = new ArrayList (); for (String json : jsons){ pileline.add(Document.parse(json)); } List results = collection.aggregate(pileline).into(new ArrayList ()); for (Document cur : results) { System.out.println(cur.toJson()); } } /** * 测试所有聚合操作 */ @Test public void testAggregate() { /*$project操作 MongoCollection collection = getCollection("user"); aggregate(collection, AggregateJson.USERPROJECT); */ /*查询日期 MongoCollection collection = getCollection("date"); aggregate(collection, AggregateJson.DATE_EXPRESSION);*/ //$project操作与$add操作(示例:perStuTotalScore) /*MongoCollection collection = getCollection("user"); aggregate(collection, AggregateJson.PROJECT_ADD);*/ //截取name的第一个字节,与.和$sex值拼接(示例mycol集合) /*MongoCollection collection = getCollection("mycol"); aggregate(collection, AggregateJson.PROJECT_CONCAT_SUBSTR);*/ //学生总成绩排名前三甲 /*MongoCollection collection = getCollection("user"); aggregate(collection, AggregateJson.PRJECT_GROUP_SORT_LIMIT);*/ /*比较成绩高低,返回比较记录,类似java的Comparable比较器的compareTo方法,返回1,0,-1*/ /*MongoCollection collection = getCollection("user"); aggregate(collection, AggregateJson.PROJECT_CMP);*/ //判断语文成绩大小,如果大于60分显示其分数,如果小于60分则显示不合格,如果没有这个字段也会显示不合格 /*MongoCollection collection = getCollection("user"); aggregate(collection, AggregateJson.PROJECT_COND);*/ //将数组的每个值拆分为单独的文档 /*MongoCollection collection = getCollection("tree"); aggregate(collection, AggregateJson.UNWIND);*/ //distinct找出给定键不同的值,找出不同的语文成绩/* Document document = database.runCommand(Document.parse(AggregateJson.DISTINCT)); System.out.println(document.toJson());*/ }}