MongoDB的聚合是什么意思

88次阅读
没有评论

共计 13597 个字符,预计需要花费 34 分钟才能阅读完成。

本篇内容介绍了“MongoDB 的聚合是什么意思”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

MongoDB 的产生背景是在大数据环境,所谓的大数据实际上就是信息的收集汇总。那么就必须存在信息的统计操作,而这样的统计操作就称为聚合(分组统计就是一种聚合操作)。

1、取得集合的数据量
对于集合的数据量而言,在 MongoDB 里面直接使用 count()函数就可以完成了。
范例:统计 emp 表中的数据量
db.emp.count();
8

范例:模糊查询
db.emp.count({name :/ 孙 /i})
1

2、消除重复数据
在学习 SQL 的时候对于重复的数据可以使用“DISTINCE”,那么这一操作在 MongoDB 之中依然支持。
范例:查询所有 name 的信息
本次的操作没有直接的函数支持,只能够利用 Command()指令。
db.runCommand({distinct : emp , key : name})
{
  values : [
  赵一 ,
  钱二 ,
  孙三 ,
  李四 ,
  周五 ,
  吴六 ,
  郑七 ,
  王八
  ],
  ok : 1
}

此时实现了对于 name 数据重复值的筛选。

3、group 操作
使用“group”操作可以实现数据的分组操作,在 MongoDB 里面会将集合依据指定的 key 进行分组操作。并且每一组都会产生一个处理的文档结果。
范例:查询所有年龄大于等于 30 岁的人员,并且按照年龄分组
db.runCommand({group :{
… ns : emp ,
… key :{age :true},
… initial :{count :0},
… condition :{age :{ $gte :30}},
… $reduce :function(doc,prev){prev.count++;}
… }})
{
  retval : [
  {
  age : 30,
  count : 4
  },
  {
  age : 40,
  count : 1
  },
  {
  age : 50,
  count : 1
  },
  {
  age : 35,
  count : 2
  }
  ],
  count : NumberLong(8),
  keys : NumberLong(4),
  ok : 1
}

以上的操作代码就属于一种 MapReduce,很少这样写。这样只是根据传统的数据库的设计思路,实现了一个所谓的分组操作。但是这个分组操作最终结果是有限的。

4、MapReduce
MapReduce 是整个大数据的精髓所在(实际中别用),所谓的 MapReduce 实际上就是分为两步处理数据:
  ● Map:将数据分别取出
  ● Reduce:负责数据的最后处理
可是要想在 MongoDB 里面实现 MapReduce 处理,那么复杂度是相当高的。

范例:创建一组人员数据
db.emps.insert({name : 赵一 , age :30, sex : 女 , job : CLERK , sal :1000});
db.emps.insert({name : 钱二 , age :22, sex : 男 , job : ACCOUNT , sal :2000});
db.emps.insert({name : 孙三 , age :28, sex : 女 , job : CLERK , sal :3000});
db.emps.insert({name : 李四 , age :35, sex : 女 , job : IT , sal :4000});
db.emps.insert({name : 周五 , age :31, sex : 男 , job : SEC , sal :5000});
db.emps.insert({name : 吴六 , age :40, sex : 女 , job : MANAGER , sal :6000});
db.emps.insert({name : 郑七 , age :44, sex : 男 , job : CLERK , sal :1500});
db.emps.insert({name : 王八 , age :55, sex : 男 , job : SAL , sal :5500});

使用 MapReduce 操作最终会将处理结果保存在一个单独的集合里面,而最终的处理效果如下:

范例:按照职位分组,取得每个职位的姓名
第一步:编写分组的定义:
var jobMapFun=function(){
emit(this.job,this.name);
}
第二步:编写 Reduce 操作:
var jobReduceFun=function(key,values){
… return {job :key, name :values};
… }
第三步:针对于 MapReduce 处理完成的数据实际上也可以执行一个最后处理。
var jobFinalizeFun=function(key,values){
if(key== MANAGER){
return {job :key, name :values, info : 公司老大}
return {job :key, name :values};
}
进行操作的整合:
db.runCommand({
mapreduce : emps ,
map :jobMapFun,
reduce :jobReduceFun,
out : t_emps_job ,
finalize :jobFinalizeFun});
{
  result : t_emps_job ,
  timeMillis : 28,
  counts : {
  input : 8,
  emit : 8,
  reduce : 1,
  output : 6
  },
  ok : 1
}
现在执行之后,所有的处理结果都保存在了 t_emps_job 集合里面。
db.t_emps_job.find();
{_id : ACCOUNT , value : { job : ACCOUNT , name : 钱二} }
{_id : CLERK , value : { job : CLERK , name : { job : CLERK , name : [ 赵一 , 孙三 , 郑七] } } }
{_id : IT , value : { job : IT , name : 李四} }
{_id : MANAGER , value : { job : MANAGER , name : 吴六 , info : 公司老大} }
{_id : SAL , value : { job : SAL , name : 王八} }
{_id : SEC , value : { job : SEC , name : 周五} }

范例:统计出各性别的人数,平均工资,最低工资,雇员姓名
var sexMapFun=function(){
emit(this.sex,{ ccount :1, csal :this.sal, cmax :this.sal, cmin :this.sal, cname :this.name}); // 定义分组的条件以及每个集合要取出的内容
}

var sexReduceFun=function(key,values){
var total=0; // 统计
var sum=0; // 计算总工资
var max=values[0].cmax; // 假设第一个数据是最高工资
var min=values[0].cmin; // 假设第一个数据是最低工资
var names=new Array(); // 定义数组内容
for (var x in values){// 循环取出里面的数据
total += values[x].ccount; // 人数增加
sum += values[x].csal; // 循环取出所有的工资,并且累加
if (max values[x].cmax){
max=values[x].cmax; // 找到最高工资
}
if (min values[x].cmin){
min=values[x].cmin; // 找到最低工资
}
names[x]=values[x].cname; // 保存姓名
}
var avg=(sum/total).toFixed(2);
return {count :total, avg :avg, max :max, min :min, name :names};
}; // 返回数据处理结果

db.runCommand({
mapreduce : emps ,
map :sexMapFun,
reduce :sexReduceFun,
out : t_emps_sex
})
{
  result : t_emps_sex ,
  timeMillis : 31,
  counts : {
  input : 8,
  emit : 8,
  reduce : 2,
  output : 2
  },
  ok : 1
}

db.t_emps_sex.find().pretty();
{
  _id : 女 ,
  value : {
  count : 4,
  avg : 3500.00 ,
  max : 6000,
  min : 1000,
  name : [
  赵一 ,
  孙三 ,
  李四 ,
  吴六
  ]
  }
}
{
  _id : 男 ,
  value : {
  count : 4,
  avg : 3500.00 ,
  max : 5500,
  min : 1500,
  name : [
  钱二 ,
  周五 ,
  郑七 ,
  王八
  ]
  }
}

虽然大数据时代提供有最强悍的 MapReduce 支持,但是从现实的开发来讲,真的不可能使用起来。

5、聚合框架
MapReduce 功能强大,但是复杂度太大,很多时候需要 MapReduce 功能,可是又不想把代码写得太复杂。所以在 MongoDB 2.x 版本之后开始引入了聚合框架并且提供了聚合函数:aggregate()。

5.1 $group
group 主要进行分组的数据操作。
范例:实现聚合查询的功能 – 求出每个职位的人员数量
db.emps.aggregate([{$group :{ _id : $job ,job_count:{ $sum :1}}}])
{_id : MANAGER , job_count : 1}
{_id : ACCOUNT , job_count : 1}
{_id : IT , job_count : 1}
{_id : SAL , job_count : 1}
{_id : CLERK , job_count : 3}
{_id : SEC , job_count : 1}

这样的操作更加符合传统的 group by 子句的操作使用。

范例:求出每个职位的总工资
db.emps.aggregate([{$group :{ _id : $job ,job_sal:{ $sum : $sal}}}])
{_id : MANAGER , job_sal : 6000}
{_id : ACCOUNT , job_sal : 2000}
{_id : IT , job_sal : 4000}
{_id : SAL , job_sal : 5500}
{_id : CLERK , job_sal : 5500}
{_id : SEC , job_sal : 5000}

在整个聚合框架里面如果要引用每行的数据使用:$ 字段名称。

范例:计算出每个职位的平均工资
db.emps.aggregate([{$group :{ _id : $job , job_sal :{ $sum : $sal}, job_avg :{$avg : $sal}}}])
{_id : MANAGER , job_sal : 6000, job_avg : 6000}
{_id : ACCOUNT , job_sal : 2000, job_avg : 2000}
{_id : IT , job_sal : 4000, job_avg : 4000}
{_id : SAL , job_sal : 5500, job_avg : 5500}
{_id : CLERK , job_sal : 5500, job_avg : 1833.3333333333333}
{_id : SEC , job_sal : 5000, job_avg : 5000}

范例:求出最高与最低工资
db.emps.aggregate([{$group :{ _id : $job , max_sal :{ $max : $sal}, min_avg :{$min : $sal}}}])
{_id : MANAGER , max_sal : 6000, min_avg : 6000}
{_id : ACCOUNT , max_sal : 2000, min_avg : 2000}
{_id : IT , max_sal : 4000, min_avg : 4000}
{_id : SAL , max_sal : 5500, min_avg : 5500}
{_id : CLERK , max_sal : 3000, min_avg : 1000}
{_id : SEC , max_sal : 5000, min_avg : 5000}

以上的几个与 SQL 类似的操作计算成功实现了。

范例:计算出每个职位的工资数据(数组显示)
db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $push : $sal}}}])
{_id : MANAGER , sal_data : [ 6000] }
{_id : ACCOUNT , sal_data : [ 2000] }
{_id : IT , sal_data : [ 4000] }
{_id : SAL , sal_data : [ 5500] }
{_id : CLERK , sal_data : [ 1000, 3000, 1500] }
{_id : SEC , sal_data : [ 5000] }

范例:求出每个职位的人员
db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $push : $name}}}])
{_id : MANAGER , sal_data : [ 吴六] }
{_id : ACCOUNT , sal_data : [ 钱二] }
{_id : IT , sal_data : [ 李四] }
{_id : SAL , sal_data : [ 王八] }
{_id : CLERK , sal_data : [ 赵一 , 孙三 , 郑七] }
{_id : SEC , sal_data : [ 周五] }

使用“$push”的确可以将数据变为数组进行保存,但是有一个问题出现了,重复的内容也会进行保存,那么在 MongoDB 里面提供有取消重复的设置。
db.emps.insert({name : 吴六 , age :40, sex : 女 , job : MANAGER , sal :6000});
WriteResult({nInserted : 1})
db.emps.insert({name : 郑七 , age :44, sex : 男 , job : CLERK , sal :1500});
WriteResult({nInserted : 1})
db.emps.insert({name : 王八 , age :55, sex : 男 , job : SAL , sal :5500});
WriteResult({nInserted : 1})

db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $push : $name}}}])
{_id : MANAGER , sal_data : [ 吴六 , 吴六] }
{_id : ACCOUNT , sal_data : [ 钱二] }
{_id : IT , sal_data : [ 李四] }
{_id : SAL , sal_data : [ 王八 , 王八] }
{_id : CLERK , sal_data : [ 赵一 , 孙三 , 郑七 , 郑七] }
{_id : SEC , sal_data : [ 周五] }

范例:取消重复的数据
db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $addToSet : $name}}}])
{_id : MANAGER , sal_data : [ 吴六] }
{_id : ACCOUNT , sal_data : [ 钱二] }
{_id : IT , sal_data : [ 李四] }
{_id : SAL , sal_data : [ 王八] }
{_id : CLERK , sal_data : [ 郑七 , 孙三 , 赵一] }
{_id : SEC , sal_data : [ 周五] }

默认情况下是将所有的数据都保存进去了,但是现在只希望可以保留第一个或者是最后一个。

范例:保存第一个内容
db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $first : $name}}}])
{_id : MANAGER , sal_data : 吴六}
{_id : ACCOUNT , sal_data : 钱二}
{_id : IT , sal_data : 李四}
{_id : SAL , sal_data : 王八}
{_id : CLERK , sal_data : 赵一}
{_id : SEC , sal_data : 周五}

范例:保存最后一个内容
db.emps.aggregate([{$group :{ _id : $job , sal_data :{ $last : $name}}}])
{_id : MANAGER , sal_data : 吴六}
{_id : ACCOUNT , sal_data : 钱二}
{_id : IT , sal_data : 李四}
{_id : SAL , sal_data : 王八}
{_id : CLERK , sal_data : 郑七}
{_id : SEC , sal_data : 周五}

虽然可以方便的实现分组处理,但是有一点需要注意,所有的分组数据是无序的,并且都是在内存之中完成的,所以不可能支持大数据量。

5.2 $project
可以利用 $project 来控制数据列的显示规则,规则如下:
  ● 普通列({成员:1|true}):表示要显示的内容
  ●“_id”列({_id :0|false}):表示“_id”列是否显示
  ● 条件过滤列({成员: 表达式}):满足表达式之后的数据可以进行显示

范例:只显示 name、job 列,不显示_id 列
db.emps.aggregate([{$project :{ _id :0, name :1}}])
{name : 赵一}
{name : 钱二}
{name : 孙三}
{name : 李四}
{name : 周五}
{name : 吴六}
{name : 郑七}
{name : 王八}
{name : 吴六}
{name : 郑七}
{name : 王八}

此时只有设置进去的列才可以被显示出来,而其他的列不能被显示出来。实际上这就属于数据库的投影机制。
实际上在数据投影的过程里面也支持四则运算:加法($add)、减法($subtract)、乘法(“$mulitipy”)、除法(“”$devided)、求模($mod)

范例:四则运算
db.emps.aggregate([{$project :{ _id :0, name :1, 职位 : $job , sal :1}}])
{name : 赵一 , sal : 1000, 职位 : CLERK}
{name : 钱二 , sal : 2000, 职位 : ACCOUNT}
{name : 孙三 , sal : 3000, 职位 : CLERK}
{name : 李四 , sal : 4000, 职位 : IT}
{name : 周五 , sal : 5000, 职位 : SEC}
{name : 吴六 , sal : 6000, 职位 : MANAGER}
{name : 郑七 , sal : 1500, 职位 : CLERK}
{name : 王八 , sal : 5500, 职位 : SAL}
{name : 吴六 , sal : 6000, 职位 : MANAGER}
{name : 郑七 , sal : 1500, 职位 : CLERK}
{name : 王八 , sal : 5500, 职位 : SAL}

db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 年薪 :{ $multiply :[ $sal ,12]}}}])
{name : 赵一 , job : CLERK , 年薪 : 12000}
{name : 钱二 , job : ACCOUNT , 年薪 : 24000}
{name : 孙三 , job : CLERK , 年薪 : 36000}
{name : 李四 , job : IT , 年薪 : 48000}
{name : 周五 , job : SEC , 年薪 : 60000}
{name : 吴六 , job : MANAGER , 年薪 : 72000}
{name : 郑七 , job : CLERK , 年薪 : 18000}
{name : 王八 , job : SAL , 年薪 : 66000}
{name : 吴六 , job : MANAGER , 年薪 : 72000}
{name : 郑七 , job : CLERK , 年薪 : 18000}
{name : 王八 , job : SAL , 年薪 : 66000}

除了四则运算之外也支持如下的各种运算符:
  ● 关系运算:大小比较($cmp)、等于($eq)、大于($gt)、大于等于($gte)、小于($lt)、小于等于($lte)、不等于($ne)、判断 NULL($ifNull),这些操作返回的结果都是布尔型数据。
  ● 逻辑运算:与($and)、或($or)、非($not)
  ● 字符串操作:连接($concat)、截取($substr)、转小写($toLower)、转大小($toUpper)、不区分大小写比较($strcasecmp)

范例:找出所有薪水大于等于 2000 的人员姓名,职位和薪水
db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 工资 : $sal , 是否大于 2000 :{ $gte :[ $sal ,2000]}}}])
{name : 赵一 , job : CLERK , 工资 : 1000, 是否大于 2000 : false}
{name : 钱二 , job : ACCOUNT , 工资 : 2000, 是否大于 2000 : true}
{name : 孙三 , job : CLERK , 工资 : 3000, 是否大于 2000 : true}
{name : 李四 , job : IT , 工资 : 4000, 是否大于 2000 : true}
{name : 周五 , job : SEC , 工资 : 5000, 是否大于 2000 : true}
{name : 吴六 , job : MANAGER , 工资 : 6000, 是否大于 2000 : true}
{name : 郑七 , job : CLERK , 工资 : 1500, 是否大于 2000 : false}
{name : 王八 , job : SAL , 工资 : 5500, 是否大于 2000 : true}
{name : 吴六 , job : MANAGER , 工资 : 6000, 是否大于 2000 : true}
{name : 郑七 , job : CLERK , 工资 : 1500, 是否大于 2000 : false}
{name : 王八 , job : SAL , 工资 : 5500, 是否大于 2000 : true}

范例:查询职位是 manager 的信息
db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 职位 : $job , job :{ $eq :[ $job , MANAGER]}}}])
{name : 赵一 , job : false, 职位 : CLERK}
{name : 钱二 , job : false, 职位 : ACCOUNT}
{name : 孙三 , job : false, 职位 : CLERK}
{name : 李四 , job : false, 职位 : IT}
{name : 周五 , job : false, 职位 : SEC}
{name : 吴六 , job : true, 职位 : MANAGER}
{name : 郑七 , job : false, 职位 : CLERK}
{name : 王八 , job : false, 职位 : SAL}
{name : 吴六 , job : true, 职位 : MANAGER}
{name : 郑七 , job : false, 职位 : CLERK}
{name : 王八 , job : false, 职位 : SAL}

db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 职位 : $job , job :{ $eq :[ $job ,{ $toUpper : manager}]}}}])
{name : 赵一 , job : false, 职位 : CLERK}
{name : 钱二 , job : false, 职位 : ACCOUNT}
{name : 孙三 , job : false, 职位 : CLERK}
{name : 李四 , job : false, 职位 : IT}
{name : 周五 , job : false, 职位 : SEC}
{name : 吴六 , job : true, 职位 : MANAGER}
{name : 郑七 , job : false, 职位 : CLERK}
{name : 王八 , job : false, 职位 : SAL}
{name : 吴六 , job : true, 职位 : MANAGER}
{name : 郑七 , job : false, 职位 : CLERK}
{name : 王八 , job : false, 职位 : SAL}

db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 职位 : $job , job :{ $strcasecmp :[ $job , manager]}}}])
{name : 赵一 , job : -1, 职位 : CLERK}
{name : 钱二 , job : -1, 职位 : ACCOUNT}
{name : 孙三 , job : -1, 职位 : CLERK}
{name : 李四 , job : -1, 职位 : IT}
{name : 周五 , job : 1, 职位 : SEC}
{name : 吴六 , job : 0, 职位 : MANAGER}
{name : 郑七 , job : -1, 职位 : CLERK}
{name : 王八 , job : 1, 职位 : SAL}
{name : 吴六 , job : 0, 职位 : MANAGER}
{name : 郑七 , job : -1, 职位 : CLERK}
{name : 王八 , job : 1, 职位 : SAL}

范例:使用字符串截取
db.emps.aggregate([{$project :{ _id :0, name :1, job :1, 职位 : $job , job :{ 前面三位 :{ $substr :[ $job ,0,3]}}}}])
{name : 赵一 , job : { 前面三位 : CLE}, 职位 : CLERK }
{name : 钱二 , job : { 前面三位 : ACC}, 职位 : ACCOUNT }
{name : 孙三 , job : { 前面三位 : CLE}, 职位 : CLERK }
{name : 李四 , job : { 前面三位 : IT}, 职位 : IT }
{name : 周五 , job : { 前面三位 : SEC}, 职位 : SEC }
{name : 吴六 , job : { 前面三位 : MAN}, 职位 : MANAGER }
{name : 郑七 , job : { 前面三位 : CLE}, 职位 : CLERK }
{name : 王八 , job : { 前面三位 : SAL}, 职位 : SAL }
{name : 吴六 , job : { 前面三位 : MAN}, 职位 : MANAGER }
{name : 郑七 , job : { 前面三位 : CLE}, 职位 : CLERK }
{name : 王八 , job : { 前面三位 : SAL}, 职位 : SAL }

利用 $project 实现的投影操作功能相当强大,所有可能出现的操作几乎都能够使用。

5.3、$sort
使用 $sort 可以实现排序,设置 1 表示升序,设置 - 1 表示降序。
范例:实现排序
db.emps.aggregate([{$project :{ _id :0, age :1, sal :1}},{$sort :{ age :-1, sal :1}}])
{age : 55, sal : 5500}
{age : 55, sal : 5500}
{age : 44, sal : 1500}
{age : 44, sal : 1500}
{age : 40, sal : 6000}
{age : 40, sal : 6000}
{age : 35, sal : 4000}
{age : 31, sal : 5000}
{age : 30, sal : 1000}
{age : 28, sal : 3000}
{age : 22, sal : 2000}

db.emps.aggregate([{$match :{ sal :{ $gte :3000, $lte :5000}}},{$project :{ _id :0, age :1, sal :1}},{$sort :{ age :-1, sal :1}}])
{age : 35, sal : 4000}
{age : 31, sal : 5000}
{age : 28, sal : 3000}

db.emps.aggregate([
… {$match :{ sal :{ $gte :3000, $lte :6000}}},
… {$project :{ _id :0, age :1, sal :1}},
… {$group :{ _id : $age , count :{ $sum :1}}},
… {$sort :{ count :-1}}])
{_id : 55, count : 2}
{_id : 40, count : 2}
{_id : 28, count : 1}
{_id : 35, count : 1}
{_id : 31, count : 1}

db.emps.aggregate([
… {$match :{ sal :{ $gte :3000, $lte :6000}}},
… {$project :{ _id :0, name :1, sal :1, job :1}},
… {$group :{ _id : $job , count :{ $sum :1}, avg :{$avg : $sal}}},
… {$sort :{ count :-1}}])
{_id : SAL , count : 2, avg : 5500}
{_id : MANAGER , count : 2, avg : 6000}
{_id : IT , count : 1, avg : 4000}
{_id : CLERK , count : 1, avg : 3000}
{_id : SEC , count : 1, avg : 5000}

5.4、分页处理:$limit、$skip
$limit:数据取出个数
“$skip”:数据跨过个数
范例:使用“$limit”设置取出个数
db.emps.aggregate([
… {$project :{ _id :0, name :1, sal :1}},
… {$limit :2}
… ])
{name : 赵一 , sal : 1000}
{name : 钱二 , sal : 2000}

范例:跨过 3 行数据
db.emps.aggregate([
… {$project :{ _id :0, name :1, sal :1}},
… {$skip :3},
… {$limit :2}
… ])
{name : 李四 , sal : 4000}
{name : 周五 , sal : 5000}

db.emps.aggregate([
… {$match :{ sal :{ $gte :3000, $lte :6000}}},
… {$project :{ _id :0, name :1, sal :1, job :1}},
… {$group :{ _id : $job , count :{ $sum :1}, avg :{$avg : $sal}}},
… {$sort :{ count :-1}},
… {$skip :3},
… {$limit :2}
… ])
{_id : IT , count : 1, avg : 4000}
{_id : CLERK , count : 1, avg : 3000}

5.5 $unwind
在查询数据的时候经常会返回数组信息,但是数组并不方便信息的浏览,所以提供有 $unwind 可以将数组数据变为对立的字符串内容。
范例:添加一些信息
db.depts.insert({title : 技术部 , busi :[ 研发 , 生产 , 培训]});
db.depts.insert({title : 技术部 , busi :[ 薪酬 , 税务]});

范例:将信息进行转化
db.depts.aggregate([
… {$project :{ _id :0, title :1, busi :1}},
… {$unwind : $busi}
… ]);
{title : 技术部 , busi : 研发}
{title : 技术部 , busi : 生产}
{title : 技术部 , busi : 培训}
{title : 技术部 , busi : 薪酬}
{title : 技术部 , busi : 税务}

此时相当于将数组的数据变为了单行的数据。

5.6 $geoNear
使用 $geoNear 可以得到附件的坐标点。
范例:准备测试数据
db.shop.drop();
db.shop.insert({loc:[10,10]});
db.shop.insert({loc:[20,10]});
db.shop.insert({loc:[10,20]});
db.shop.insert({loc:[20,20]});
db.shop.insert({loc:[100,100]});
db.shop.insert({loc:[80,30]});
db.shop.insert({loc:[30,50]});
db.shop.createIndex({loc : 2d})

范例:设置查询
db.shop.aggregate([
… {$geoNear :{ near :[30,30], distanceField : loc , maxDistance :20, num :2}}
… ])
{_id : ObjectId( 5994ff7c0184ff511bf02bdc), loc : 14.142135623730951 }
{_id : ObjectId( 5994ff7d0184ff511bf02bdf), loc : 20 }

地理信息的检索必须存在索引的支持。

5.7 $out
$out 可以将查询结果输出到指定的集合里面。
范例:将投影的结果输出到集合里
db.emps.aggregate([
… {$project :{ _id :0, name :1, sal :1}},
… {$out : emps_infos}
… ])
db.emps_infos.find();
{_id : ObjectId( 599501eeca6455d4a46874e0), name : 赵一 , sal : 1000 }
{_id : ObjectId( 599501eeca6455d4a46874e1), name : 钱二 , sal : 2000 }
{_id : ObjectId( 599501eeca6455d4a46874e2), name : 孙三 , sal : 3000 }
{_id : ObjectId( 599501eeca6455d4a46874e3), name : 李四 , sal : 4000 }
{_id : ObjectId( 599501eeca6455d4a46874e4), name : 周五 , sal : 5000 }
{_id : ObjectId( 599501eeca6455d4a46874e5), name : 吴六 , sal : 6000 }
{_id : ObjectId( 599501eeca6455d4a46874e6), name : 郑七 , sal : 1500 }
{_id : ObjectId( 599501eeca6455d4a46874e7), name : 王八 , sal : 5500 }
{_id : ObjectId( 599501eeca6455d4a46874e8), name : 吴六 , sal : 6000 }
{_id : ObjectId( 599501eeca6455d4a46874e9), name : 郑七 , sal : 1500 }
{_id : ObjectId( 599501eeca6455d4a46874ea), name : 王八 , sal : 5500 }

相当于实现了数据表的复制操作。

“MongoDB 的聚合是什么意思”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-01发表,共计13597字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)