mongodb使用aggregate、group、match实现mysql中的having(count(1)>1)的功能

关系型数据库中分组去重一般都是group by … having(count(1)>1)…赛选出来重复的记录组,然后一条sql搞定,但是在mongodb里面,没有这么方便了,需要自己写脚本来实现,可以通过aggregate、group、match来操作处理。

1,准备录入测试数据

db.stu.insert({cid:1,age:14,name:‘gom1‘});
db.stu.insert({cid:1,age:12,name:‘jack2‘});
db.stu.insert({cid:2,age:13,name:‘Lily3‘});
db.stu.insert({cid:2,age:14,name:‘tony4‘});
db.stu.insert({cid:2,age:9,name:‘Harry5‘});
db.stu.insert({cid:2,age:13,name:‘Vincent6‘});
db.stu.insert({cid:1,age:14,name:‘bill7‘});
db.stu.insert({cid:2,age:17,name:‘tim8‘});
db.stu.insert({cid:1,age:10,name:‘bruce9‘});
db.stu.insert({cid:3,age:20,name:‘luxi10‘});

执行窗口显示如下:

mongos> use test;
switched to db test
mongos>
mongos> db.stu.insert({cid:1,age:14,name:‘gom1‘});
mongos> db.stu.insert({cid:1,age:12,name:‘jack2‘});
mongos> db.stu.insert({cid:2,age:13,name:‘Lily3‘});
mongos> db.stu.insert({cid:2,age:14,name:‘tony4‘});
mongos> db.stu.insert({cid:2,age:9,name:‘Harry5‘});
mongos> db.stu.insert({cid:2,age:13,name:‘Vincent6‘});
mongos> db.stu.insert({cid:1,age:14,name:‘bill7‘});
mongos> db.stu.insert({cid:2,age:17,name:‘tim8‘});
mongos> db.stu.insert({cid:1,age:10,name:‘bruce9‘});
mongos> db.stu.insert({cid:3,age:20,name:‘luxi10‘});

2,开始分组测试,按照cid进行分组

2.1,先统计分组记录数

var group=([

{group:{_id:"cid", max_age: {max:"age"},count: { sum: 1 }}},  
     {sort:{count:-1}}

])

执行窗口如下:

mongos> var group=([
...      {$group:{_id:"$cid", max_age: {$max:"$age"},count: { $sum: 1 }}},
...      {$sort:{count:-1}}
... ])
mongos>

2.2,定义就是找出存在重复的分组,使用管道操作符match,条件是普通查询的格式,但是作用于group的输出结果的格式:

var match ={“match":{"count" : {"gt” : 1}}};

执行窗口如下:

mongos> var match ={"$match":{"count" : {"$gt" : 1}}};
mongos>

3 获取数据

mongos> db.stu.aggregate(group, match);
{
    "result" : [
        {
            "_id" : 2,
            "max_age" : 17,
            "count" : 5
        },
        {
            "_id" : 1,
            "max_age" : 14,
            "count" : 4
        },
        {
            "_id" : 3,
            "max_age" : 20,
            "count" : 1
        }
    ],
    "ok" : 1
}
mongos> 

PS:这里match无效,出来count为1的数据,没有match成功,问题在哪里呢?

网友Traveller的指点:

db.stu.aggregate(group, match); 看出来了吗?你这样调用相当于把match作为options传进去了,当然没有用,这种方法得不到最终的数据,因为每个管道是数组的一个元素,而group单独是一个数组,match是一个元素。除非把它加进数组里面,看如下写法,

group.push(match);

db.stu.aggregate(group);

然后自己去看官网进一步研究:

http://docs.mongoing.com/manual-zh/reference/method/db.collection.aggregate.html#db.collection.aggregate,查看了aggregate介绍,aggregate的方法签名是function (pipeline, aggregateOptions),

第一个参数是piplines,所有的对数据的判断条件都应该在这里面。

第二个参数是options,指定查询时候使用的一些选项。

The options document can contain the following fields and values:包括explain、allowDiskUse、cursor,所以我传入的match是针对group的判断条件,所以不能作为第二个参数,而应该放到第一个参数里面去,所以需要用到group的push功能,将match加入第一个参数里面去才能使count>1的判断生效。


4,使用group的push功能

mongos> group.push(match);
3
mongos> db.stu.aggregate(group);
{
    "result" : [
        {
            "_id" : 2,
            "max_age" : 17,
            "count" : 5
        },
        {
            "_id" : 1,
            "max_age" : 14,
            "count" : 4
        }
    ],
    "ok" : 1
}
mongos> 

看到已经过滤掉了count=1的记录组了,表示push成功了。

时间: 2024-10-05 13:33:00

mongodb使用aggregate、group、match实现mysql中的having(count(1)>1)的功能的相关文章

mysql中case when 用于分类求和

假设有张学生成绩表(CJ)如下 [姓名] [学科] [成绩] 张三 语文 80 张三 数学 90 张三 物理 85 李四 语文 85 李四 数学 92 李四 物理 82 王五 数学 60 想变成 [姓名] [语文] [数学] [物理] 张三 80 90 85 李四 85 92 82 王五 null 60 null select 姓名,sum(case 学科 when '语文' then 成绩 end) as 语文,sum(case 学科 when '数学' then 成绩 end) as 数学,

mysql中的count()函数使用

有时候总认为count(*)会比count(1)或者count(column name)慢,事实上是分情况处理. 比如: ---初始化语句 建立一张表并插入数据: create table test2 (id BIGINT PRIMARY key, name varchar(24))ENGINE=INNODB; insert into test2(id,name)values(1,null); insert into test2(id,name)values(2,'name1'); insert

mysql中的基础查询 练习

#进阶1:基础查询 /* 语法: select 查询列表 from 表名; 类似于:System.out.println(打印东西); 特点: 1.查询列表可以是:表中的字段.常量值.表达式.函数 2.查询的结果是一个虚拟的表格 */ USE myemployees; #1.查询表中的单个字段 SELECT last_name FROM employees; #2.查询表中的多个字段 SELECT last_name,salary,email FROM employees; #3.查询表中的所有

MySQL中的函数索引(Generated Column)及一次SQL优化

MySQL 中是没有 Oracle 的函数索引功能的,把 MySQL 的 Generated Column 称为"函数索引"并不准确,但可以和函数索引达到同样的效果,也有人把这个特性称为"衍生列". Generated Column 是什么 Generated Column 的值是根据其定义的表达式所计算而来的,下面使用官方文档中的例子做个简单介绍. 有一张表存储直角三角形的三条边长,大家都知道,根据直角三角形的边长公式,斜边的长度可以通过另外两条边长计算得到,这样

mysql SELECT FOUND_ROWS()与COUNT(*)用法区别

在mysql中 FOUND_ROWS()与COUNT(*)都可以统计记录,如果都一样为什么会有两个这样的函数呢,下面我来介绍SELECT FOUND_ROWS()与COUNT(*)用法区别 SELECT语句中经常可能用LIMIT限制返回行数.有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句.那么,在SELECT查询中包含SQL_CALC_FOUND_ROWS选项,然后执行FOUND_ROWS()就可以了:  代码如下 复制代码 mysql> SELECT SQL_CA

php学习之道:mysql SELECT FOUND_ROWS()与COUNT(*)用法区别

在mysql中 FOUND_ROWS()与COUNT(*)都可以统计记录,如果都一样为什么会有两个这样的函数呢,下面我来介绍SELECT FOUND_ROWS()与COUNT(*)用法区别 SELECT语句中经常可能用LIMIT限制返回行数.有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句.那么,在SELECT查询中包含SQL_CALC_FOUND_ROWS选项,然后执行FOUND_ROWS()就可以了:  代码如下 复制代码 mysql> SELECT SQL_CA

MongoDB聚合操作 (group, aggregate, mapReduce操作)

#MongoDb 聚合方法 group aggrate mapreduce# 1. Group (不支持分片,分布计算) * 语法结构 <pre> db.collection.group({ key:{category:1}, // 根据category来分类 cond:{shop_price:{$gt:20}}, // 附加条件商品借个大于20的商品 reduce:function(curr, result){ // curr 标识一行记录, result自定义变量, }, initial:

mysql中group by和order by混用 结果不是理想结果

在使用mysql排序的时候会想到按照降序分组来获得一组数据,而使用order by往往得到的不是理想中的结果,那么怎么才能使用group by 和order by得到理想中的数据结果呢? 例如 有一个 帖子的回复表,posts( id , tid , subject , message ,  dateline ) , id为 自动增长字段, tid为该回复的主题帖子的id(外键关联),  subject 为回复标题, message 为回复内容, dateline 为回复时间,用UNIX 时间戳

GROUP BY和HAVING 以及mysql中常用的日期函数

一.mysql中的GROUP BY和HAVINGGROUP BY常见的是和聚合函数(SUM,MIN,MAX,COUNT)搭配使用. 比如:SELECT category,SUM(money) AS `total` FROM user_money GROUP BY category;按类别分组统计user_money表每个类别总计有多少money 现在如果增加个条件,需要统计每个类别中支出的money总量,比如rule=1为支出,则改写语句为SELECT category,SUM(money) A