• MongoDB中的分组


    .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])

    }

    插入完成后,查看一下:

     

    现在我有一个需求,想要找到每个国家当中年纪最大的人,并且年纪不大于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

    }

     

    从结果看到日本女士苍井空的年龄是30,被我筛选掉了…...

     

    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.之前我们遇到删除集合,一般使用的方法是 db.集合名.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"

            }

    })

    >

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

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

     

     

     

     

     

     

     

     

  • 相关阅读:
    第二章、Java内存区域与内存溢出异常
    第二章、Java内存区域与内存溢出异常
    腾讯//格雷编码
    腾讯//格雷编码
    数据结构5.5_广义表的递归算法
    数据结构5.4_m元多项式的表示
    数据结构4.2_串操作应用举例_建立词索引表
    数据结构3_栈和队列
    数据结构2_线性表
    数据结构1_绪论
  • 原文地址:https://www.cnblogs.com/dcz2015/p/5314273.html
Copyright © 2020-2023  润新知