mongodb 聚合函数

1.count
这个函数很好理解,和其他数据库一样,就是做一个count操作
select count(*) from tab1 =db.tab1.count()
以上例子很好理解,但是如果在操作中有skip,limit这种操作的话,那么count会忽略掉这些操作,必须加入一个true参数
比如:db.tab1.find().skip(1),limit(2).count()和db.tab1.find().count()得出的结果是一样的
必须修改为db.tab1.find().skip(1).limit(2).count(true)
2.distinct
去重函数,这个也应该很熟悉,各种关系数据库都有
具体操作:db.runCommand({"distinct":"collection","key":"xxxx"})=db.collections.distinct("xxxx");
3.group
selecta,b,sum(c)csumfromcollwhereactive=1group bya,b

db.coll.group( {key: { a:true, b:true },

cond: { active:1 },

reduce:function(obj,prev){prev.csum+=obj.c; },

initial: {csum: 0 }

});

参数解释:

Key:group字段
Reduce:聚合函数,典型的有sumcount操作,包含两个参数,当前遍历对象以及聚合计数器
Initial:初始化计数器值
Cond:查询条件筛选选项,如果是空,那么默认对当前collection的所有行操作
Group不能在sharding中使用,结果输出不能多于10000keys
举例:

> db.mtb1.find()
{ "_id" : ObjectId("4fb4be52aa814943b788095c"), "name" : "aaa", "score" : 77 }
{ "_id" : ObjectId("4fb4be5caa814943b788095d"), "name" : "bbb", "score" : 79 }
{ "_id" : ObjectId("4fb4be61aa814943b788095e"), "name" : "ccc", "score" : 79 }
{ "_id" : ObjectId("4fb4be69aa814943b788095f"), "name" : "ddd", "score" : 79 }
{ "_id" : ObjectId("4fb4be74aa814943b7880960"), "name" : "eee", "score" : 100 }
{ "_id" : ObjectId("4fb4be7aaa814943b7880961"), "name" : "fff", "score" : 100 }
{ "_id" : ObjectId("4fb4be82aa814943b7880962"), "name" : "ggg", "score" : 100 }
{ "_id" : ObjectId("4fb4be9eaa814943b7880963"), "name" : "hhh", "score" : 200}

> db.mtb1.group(
... {key:{score:true},
... reduce:function(obj,prev){prev.count++;},
... initial:{count:0}
... });
[
{
"score" : 77,
"count" : 1
},
{
"score" : 79,
"count" : 3
},
{
"score" : 100,
"count" : 3
},
{
"score" : 200,
"count" : 1
}
]
一个简单的例子,应该很明白了。其实这里group还是建立在reduce上面
4.map/reduce
这个工具的功能可以实现以上三种任何一种,它是分两步完成,先做map,再reduce,map首先对数据进行分解映射,map执行完,紧接着会进行reduce,map后会的到key-values,像{key:[value1,value2,value3...]},然后通过reduce处理后得到key-value,也就是单一的值。
语法:
db.runCommand(
{ mapreduce : <collection>,
map : <mapfunction>,
reduce : <reducefunction>
[, query : <query filter object>]
[, sort : <sort the query. useful for optimization>]
[, limit : <number of objects to return from collection>]
[, out : <output-collection name>]
[, keeptemp: <true|false>]
[, finalize : <finalizefunction>]
[, scope : <object where fields go into javascript global scope >]
[, verbose : true]
}
);

query是很常用的,它用来在map阶段过滤查询条件的以限定MapReduce操作的记录范围,sortlimit集合query使用。

out指定输出结果的collections名称

Keeptemp布尔型,默认是false,如果是true那么生成的collection是永久存在的,如果是false,那么在客户端连接关闭后,会自动删除生成的collection

Finalize一般用来计算平均数,裁剪数组,清多余信息

query是很常用的,它用来在map阶段过滤查询条件的以限定MapReduce操作的记录范围,sortlimit集合query使用。

out指定输出结果的collections名称

Keeptemp布尔型,默认是false,如果是true那么生成的collection是永久存在的,如果是false,那么在客户端连接关闭后,会自动删除生成的collection

Finalize一般用来计算平均数,裁剪数组,清多余信息

{ result : <collection_name>,

counts : {

input : <number of objects scanned>,

emit : <number of times emit was called>,

output : <number of items in output collection>

} ,

timeMillis : <job_time>,

ok : <1_if_ok>,

[, err : <errmsg_if_error>]

}

result:储存结果的collection的名字

input:满足条件的数据行数

emit:emit调用次数,也就是所有集合中的数据总量

ouput:返回结果条数

timeMillis:执行时间,毫秒为单位

ok:是否成功,成功为1

err:如果失败,这里可以有失败原因


给出官方文档的一个例子:

$ ./mongo

> db.things.insert( { _id : 1, tags : ['dog', 'cat'] } );

> db.things.insert( { _id : 2, tags : ['cat'] } );

> db.things.insert( { _id : 3, tags : ['mouse', 'cat', 'dog'] } );

> db.things.insert( { _id : 4, tags : [] } );


> // map function

> m = function(){

... this.tags.forEach(

... function(z){

... emit( z , { count : 1 } );

... }

... );

...};


> // reduce function

> r = function( key , values ){

... var total = 0;

... for ( var i=0; i<values.length; i++ )

... total += values[i].count;

... return { count : total };

...};


> res = db.things.mapReduce(m,r);

> res

{"timeMillis.emit" : 9 , "result" : "mr.things.1254430454.3" ,

"numObjects" : 4 , "timeMillis" : 9 , "errmsg" : "" , "ok" : 0}


> db[res.result].find()

{"_id" : "cat" , "value" : {"count" : 3}}

{"_id" : "dog" , "value" : {"count" : 2}}

{"_id" : "mouse" , "value" : {"count" : 1}}


> db[res.result].drop()

### 如何在 Java 中使用 MongoDB 聚合函数 #### 使用 `MongoTemplate` 进行聚合操作 Spring Data MongoDB 提供了一个强大的工具类 `MongoTemplate`,它允许开发者通过构建管道阶段来执行复杂的聚合查询。以下是基于 Spring 的实现方式: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.MatchOperation; import org.springframework.data.mongodb.core.aggregation.SortOperation; import org.springframework.data.mongodb.core.aggregation.UnwindOperation; import org.springframework.stereotype.Service; @Service public class MongoAggregationService { @Autowired private MongoTemplate mongoTemplate; public List<Document> getSortedTweetList(String objectId) { MatchOperation matchStage = Aggregation.match( Criteria.where("_id").is(new ObjectId(objectId)) ); UnwindOperation unwindStage = Aggregation.unwind("tweet_list"); MatchOperation tweetMatchStage = Aggregation.match( Criteria.where("tweet_list.timestamp_ms").is("1451841845660") ); SortOperation sortStage = Aggregation.sort(Sort.Direction.ASC, "tweet_list.timestamp_ms"); Aggregation aggregation = Aggregation.newAggregation(matchStage, unwindStage, tweetMatchStage, sortStage); AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "text", Document.class); return results.getMappedResults(); } } ``` 上述代码展示了如何利用 `MongoTemplate` 构建一个多阶段的聚合管道[^4]。 --- #### 原生驱动器中的聚合操作 如果未使用 Spring 数据库框架,则可以依赖于 MongoDB 官方提供的原生 Java 驱动程序完成相同的任务。以下是一个不借助任何额外框架的示例: ```java import com.mongodb.client.*; import org.bson.Document; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class NativeMongoAggregation { public static void main(String[] args) { MongoClient client = MongoClients.create("mongodb://localhost:27017"); MongoDatabase database = client.getDatabase("testDb"); MongoCollection<Document> collection = database.getCollection("text"); List<Bson> pipeline = Arrays.asList( new Document("$match", new Document("_id", new ObjectId("5ca95b4bfb60ec43b5dd0db5"))), new Document("$unwind", "$tweet_list"), new Document("$match", new Document("tweet_list.timestamp_ms", "1451841845660")), new Document("$sort", new Document("tweet_list.timestamp_ms", 1)) ); AggregateIterable<Document> result = collection.aggregate(pipeline); for (Document doc : result) { System.out.println(doc.toJson()); } client.close(); } } ``` 此方法直接调用了 MongoDB 的原生 API 来定义和运行聚合管道[^2]。 --- #### 关键概念解析 - **$match**: 筛选出符合条件的文档集合。 - **$unwind**: 将数组字段拆分为多个独立的文档记录。 - **$sort**: 对结果集按照指定字段升序或降序排列。 这些操作符必须嵌套在 `$pipeline` 表达式内部才能生效[^3]。 --- ### 总结 无论是采用 Spring Data MongoDB 提供的高级抽象接口还是直接运用 MongoDB 原生驱动器,都可以灵活地实现复杂的数据聚合需求。推荐优先考虑前者以便简化开发流程并提高可维护性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值