一.MongoDB中的Count函数、Distinct函数以及分组

 准备工作,插入一个班级的文档

> for(var i=0;i<10;i++){
... db.Classes.insert({ClassName:"Class"+i,_id:i});
... }
WriteResult({ "nInserted" : 1 })
> db.Classes.find()
{ "_id" : 0, "ClassName" : "Class0" }
{ "_id" : 1, "ClassName" : "Class1" }
{ "_id" : 2, "ClassName" : "Class2" }
{ "_id" : 3, "ClassName" : "Class3" }
{ "_id" : 4, "ClassName" : "Class4" }
{ "_id" : 5, "ClassName" : "Class5" }
{ "_id" : 6, "ClassName" : "Class6" }
{ "_id" : 7, "ClassName" : "Class7" }
{ "_id" : 8, "ClassName" : "Class8" }
{ "_id" : 9, "ClassName" : "Class9" }
>

1.count函数

如上面,如果要统计班级的数目,可以使用count函数进行统计

> db.Classes.find().count()
10
>

 

2.Distinct函数

修改一下Classes文档,添加一条重复的数据

> db.Classes.insert({_id:10,ClassName:"Class9"})
WriteResult({ "nInserted" : 1 })
> db.Classes.find()
{ "_id" : 0, "ClassName" : "Class0" }
{ "_id" : 1, "ClassName" : "Class1" }
{ "_id" : 2, "ClassName" : "Class2" }
{ "_id" : 3, "ClassName" : "Class3" }
{ "_id" : 4, "ClassName" : "Class4" }
{ "_id" : 5, "ClassName" : "Class5" }
{ "_id" : 6, "ClassName" : "Class6" }
{ "_id" : 7, "ClassName" : "Class7" }
{ "_id" : 8, "ClassName" : "Class8" }
{ "_id" : 9, "ClassName" : "Class9" }
{ "_id" : 10, "ClassName" : "Class9" }

 

现在我想查询所有ClassName,去掉重复的,可以执行下面的操作。

> db.runCommand({distinct:"Classes",key:"ClassName"}).values
[
        "Class0",
        "Class1",
        "Class2",
        "Class3",
        "Class4",
        "Class5",
        "Class6",
        "Class7",
        "Class8",
        "Class9"
]
>

去重语法 db.runCommand({distinct:"数据集合名字",key:"需要去重的键"}).values

 

3.Group分组操作(比较复杂)

语法:

db.runCommand({group:{
        ns:集合名字,
 Key:分组的键对象,
 Initial:初始化累加器,
 $reduce:组分解器,
 Condition:条件,
 Finalize:组完成器
      }})

 

 1).key:用来分组文档的字段。和keyf两者必须有一个

 2).keyf:可以接受一个javascript函数。用来动态的确定分组文档的字段。和key两者必须有一个

 3).initial:reduce中使用变量的初始化

 4).reduce:执行的reduce函数。函数需要返回值。

 5).cond:执行过滤的条件。

 6).finallize:在reduce执行完成,结果集返回之前对结果集最终执行的函数。可选的。

 

具体的使用可以参考手册:http://mongodb-documentation.readthedocs.org/en/latest/reference/command/group.html

分组首先会按照key进行分组,每组的 每一个文档全要执行$reduce的方法,他接收2个参数一个是组内本条记录,一个是累加器数据.

 

新建一个persons集合,插入一下数据

var persons = [{
name:"Tom",
age:25,
country:"USA"
},
{
name:"Jack",
age:25,
country:"USA"
},
{
name:"Lucy",
age:26,
country:"USA"
},
{
name:"DaChengzi",
age:27,
country:"China"
},
{
name:"Xiaojuz",
age:26,
country:"China"
},
{
name:"DaPingguo",
age:27,
country:"China"
},
{
name:"XiaoBoluo",
age:27,
country:"China"
},
{
name:"Bangzi1",
age:26,
country:"Korea"
},
{
name:"LiShishi",
age:27,
country:"Korea"
},
{
name:"Rain",
age:21,
country:"Korea"
},
{
name:"CangJingkong",
age:30,
country:"Japan"
}]
for(var i = 0;i<persons.length;i++){
db.persons.insert(persons[i])
}

插入完成后,查看一下:

mongodb 分组统计 排序 mongodb 分组计数_shell

 

现在我有一个需求,想要找到每个国家当中年纪最大的人,并且年纪不大于30岁,输出他们的名字

 

思路:①先按照国家进行分组

②找到每个国家中年纪最小的

③判断年纪是不是小于30

 

编写查询:

db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{age:0},
$reduce:function(doc,prev){
if(doc.age>prev.age){
prev.age=doc.age;
prev.name = doc.name;
prev.country = doc.country;
}
},
condition:{age:{$lt:30}}
}})

 

运行结果:

{
        "retval" : [
         {
              "country" : "USA",
"age" : 26,
                        "name" : "Lucy"
                },
                {
                        "country" : "China",
                        "age" : 27,
                        "name" : "DaChengzi"
                },
                {
                        "country" : "Korea",
                        "age" : 27,
                        "name" : "LiShishi"
                }
        ],
        "count" : 10,
        "keys" : 3,
        "ok" : 1
}



 

Finallize的使用,如果觉得返回的东西太过单调,可以使用finalize进行再次的修改

 

例如:

db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{age:0},
$reduce:function(doc,prev){
if(doc.age>prev.age){
prev.age=doc.age;
prev.name = doc.name;
prev.country = doc.country;
}
},
finalize:function(prev){
prev.age = "Age is" +prev.age;
prev.name = "Name is " + prev.name;
prev.country = "Country is " + prev.country;
},
condition:{age:{$lt:30}}
}})

加上上面之后,查询的结果如下:

{
        "retval" : [
                {
                        "country" : "Country is USA",
                        "age" : "Age is26",
                        "name" : "Name is Lucy"
                },
                {
                        "country" : "Country is China",
                        "age" : "Age is27",
                        "name" : "Name is DaChengzi"
                },
                {
                        "country" : "Country is Korea",
                        "age" : "Age is27",
                        "name" : "Name is LiShishi"
                }
        ],
        "count" : 10,
        "keys" : 3,
        "ok" : 1
}

可以看到每一项数据前面,都加上了说明文字,所以说finialize是可以对分完组之后的数据在做一次修改的。

 

二.命令执行器(db.runCommand())

1.之前我们遇到删除集合,一般使用的方法是.集合名.drop()

使用命令执行器:

db.runCommand({drop:"集合"})

 

2.查找MongoDB为我们提供的命令

①在shell中执行:db.listCommands()

②访问网址http://127.0.0.1:28017/_commands

 

3.常用命令

三.固定集合(Capped Collection)

1.解释:就是固定size的集合呗。

2.特点:性能出色的有着固定大小的集合,以LRU(Least Recently Used最近最少使用)规则和插入顺序进行age-out(老化移出)处理,自动维护集合中对象的插入顺序,在创建时需要预先指定大小。如果空间用完,新添加的对象将会取代集合中最旧的对象永远保持最新的数据

总结就是以下:

①固定集合默认是没有索引的就算是_id也是没有索引的

②由于不需分配新的空间他的插入速度是非常快的

③固定集合的顺是确定的导致查询速度是非常快的

④最适合的是应用就是日志管理

3.使用

①创建一个固定集合

创建一个新的固定集合要求大小是100个字节,可以存储文档10个

> db.createCollection("myCapped",{size:100,capped:true,max:10})
{ "ok" : 1 }
>

 

②把一个普通集合转成固定集合

> db.runCommand({convertToCapped:"Classes",size:100000})
{ "ok" : 1 }
>

③插入数据

文档最大为10个,那么当插入11条数据的时候,会出现什么情况呢,根据之前的概念,应该是吧第一条数据踢出去,然后加入最后一条

> for(var i = 0; i<11;i++){
... db.myCapped.insert({name:"name"+i,_id:i})
... }
WriteResult({ "nInserted" : 1 })
> db.myCapped.find()
{ "_id" : 1, "name" : "name1" }
{ "_id" : 2, "name" : "name2" }
{ "_id" : 3, "name" : "name3" }
{ "_id" : 4, "name" : "name4" }
{ "_id" : 5, "name" : "name5" }
{ "_id" : 6, "name" : "name6" }
{ "_id" : 7, "name" : "name7" }
{ "_id" : 8, "name" : "name8" }
{ "_id" : 9, "name" : "name9" }
{ "_id" : 10, "name" : "name10" }
>
> db.myCapped.insert({name:"name11",_id:11})
WriteResult({ "nInserted" : 1 })
> db.myCapped.find()
{ "_id" : 2, "name" : "name2" }
{ "_id" : 3, "name" : "name3" }
{ "_id" : 4, "name" : "name4" }
{ "_id" : 5, "name" : "name5" }
{ "_id" : 6, "name" : "name6" }
{ "_id" : 7, "name" : "name7" }
{ "_id" : 8, "name" : "name8" }
{ "_id" : 9, "name" : "name9" }
{ "_id" : 10, "name" : "name10" }
{ "_id" : 11, "name" : "name11" }
>

④删除数据

> db.myCapped.remove({_id:11})
WriteResult({
        "nRemoved" : 0,
        "writeError" : {
                "code" : 10101,
                "errmsg" : "cannot remove from a capped collection: mongoDBTest.myCapped"
        }
})
>

如上例,固定集合是不能进行数据删除的。

综上:固定集合有点像一个队列,先进先出,大小不变。