图片 1

数据库命令以及定位集结,MongoDB中的分组

Posted by

如何我们要删除一个集合,可以采用db.test.drop()的方式,其实在这背后,这个函数运行的是drop命令。可以用runCommand达到同样的效果。

首先来介绍下Mongodb的基本概念:

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

我们首先新建一个集合作为测试使用:

左边一列是关系数据库的术语,右边这一列是NOSQL也就是mongodb的术语

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

> use maple1

database:       database         数据库         

> for(var i=0;i<10;i++){

switched to db maple1

table:          collection        数据库表/集合

… db.Classes.insert({ClassName:”Class”+i,_id:i});

> db.maple1.insert({‘name’:’zhanghongfeng’})

row:           document        数据记录行/文档

… }

WriteResult({ “nInserted” : 1 })

coloum:        field            数据字段/域

WriteResult({ “nInserted” : 1 })

删除掉这个集合,反馈的结果中ok:1代表成功

index:          index           索引

> db.Classes.find()

> db.runCommand({“drop”:”maple1″})

table joins:                      表连接,Mongodb不支持

{ “_id” : 0, “ClassName” : “Class0” }

{ “ns” : “maple1.maple1”, “nIndexesWas” : 1, “ok” : 1 }

primary key:     primay key       主键,Mongodb自动将id设为主键

{ “_id” : 1, “ClassName” : “Class1” }

如果操作失败了,会有errmsg提示失败的原因

首先来看数据库的概念,进入mongo后用show dbs可以查看当前所有的数据列表:此时刚安装好只有admin和local两个数据库

{ “_id” : 2, “ClassName” : “Class2” }

> db.runCommand({“drop”:”maple1″})

> show dbs

{ “_id” : 3, “ClassName” : “Class3” }

{

admin  0.000GB

{ “_id” : 4, “ClassName” : “Class4” }

“ok” : 0,

local  0.000GB

{ “_id” : 5, “ClassName” : “Class5” }

“errmsg” : “ns not found”,

use命令选择需要使用的数据库。

{ “_id” : 6, “ClassName” : “Class6” }

“code” : 26,

> use admin

{ “_id” : 7, “ClassName” : “Class7” }

“codeName” : “NamespaceNotFound”

switched to db admin

{ “_id” : 8, “ClassName” : “Class8” }

}

如果我们想创建自己的一个数据库也可以使用use命令。可以看到新建的数据库再用show dbs的时候是无法观察到的。这需要我们插入数据

{ “_id” : 9, “ClassName” : “Class9” }

如果想查看所有的命令在shell中运行db.listCommands()就可以得到所有的命令。下面列举下Mongodb最常用的命令。

> use maple

>

1 buildInfo: 返回Mongodb服务器的版本号和主机的操作系统

switched to db maple

 

> db.runCommand({“buildInfo”:1})

> show dbs

1.count函数

{

admin  0.000GB

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

“version” : “3.4.7”,

local  0.000GB

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

“gitVersion” : “cf38c1b8a0a8dca4a11737581beafef4fe120bcd”,

> db

10

“modules” : [ ],

maple

>

“allocator” : “tcmalloc”,

在插入数据前需要介绍文档和集合的概念:

 

“javascriptEngine” : “mozjs”,

文档是一组键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。一个文档的例子:{‘name’:’zhf’}。这和字典的格式是一样的。

2.Distinct函数

“sysInfo” : “deprecated”,

文档格式需要注意的是:

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

“versionArray” : [

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。 

> db.Classes.insert({_id:10,ClassName:”Class9″})

3,

文档键命名规范:

WriteResult({ “nInserted” : 1 })

4,

  • 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
  • .和$有特别的意义,只有在特定环境下才能使用。
  • 以下划线”_”开头的键是保留的(不是严格要求的)。

> db.Classes.find()

7,

集合:

{ “_id” : 0, “ClassName” : “Class0” }

0

集合就是 MongoDB 文档组,前面我们介绍术语的时候集合对应着关系数据库的table也就是表格。而文档对应关系数据库的行。因此集合可以看做是文档的集合。集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。比如,我们可以将以下不同数据结构的文档插入到集合中:

{ “_id” : 1, “ClassName” : “Class1” }

],

{‘name’:’zhf’}

{ “_id” : 2, “ClassName” : “Class2” }

“openssl” : {

{‘name’:’zhf’,’city’:’chengdu’}

{ “_id” : 3, “ClassName” : “Class3” }

“running” : “OpenSSL 1.0.2g  1 Mar 2016”,

{‘name’:’zhf’,’city’:’chengdu’,’age’:30}

{ “_id” : 4, “ClassName” : “Class4” }

“compiled” : “OpenSSL 1.0.2g  1 Mar 2016”

从这可以看出,相比与关系数据库中的数据,mongodb的数据结构更加随意。不要求每行的数据类型都一样。

{ “_id” : 5, “ClassName” : “Class5” }

},

集合的命令规范

  • 集合名不能是空字符串””。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以”system.”开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。

介绍完文档和集合,我们就来向数据库中插入一组数据。插入后通过show dbs就可以找到我们的数据库了

> db.maple.insert({“name”:”zhf”})

WriteResult({ “nInserted” : 1 })

> show dbs

admin  0.000GB

local  0.000GB

maple  0.000GB

前面db.maple.insert()命令其实是在maple数据库中的maple集合插入了一个文档{“name”:”zhf”}

通过db.集合名.find()的方式就可以查询到集合的内容

> db.maple.find()

{ “_id” : ObjectId(“5a3133be956c5a2e19343140”), “name” : “zhf” }

使用show collections的方式就可以列出所有存在的集合。

> show collections

maple

如果要删除集合,使用db.集合名.drop()的方式

> db.maple.drop()

true

> show collections

 

如果要删除数据库。采用db.dropDatabase()命令

> db.dropDatabase()

{ “dropped” : “maple”, “ok” : 1 }

> show dbs

admin  0.000GB

local  0.000GB

{ “_id” : 6, “ClassName” : “Class6” }

“buildEnvironment” : {

{ “_id” : 7, “ClassName” : “Class7” }

“distmod” : “”,

{ “_id” : 8, “ClassName” : “Class8” }

“distarch” : “x86_64”,

{ “_id” : 9, “ClassName” : “Class9” }

“cc” : “cc: cc (Ubuntu 7.1.0-13ubuntu1) 7.1.0”,

{ “_id” : 10, “ClassName” : “Class9” }

“ccflags” : “-fno-omit-frame-pointer -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Wno-nonnull-compare -Wno-error=c++1z-compat -Wno-error=noexcept-type -Wno-error=format-truncation -Wno-error=int-in-bool-context -Wno-overflow -Winvalid-pch -Werror -O2 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -fstack-protector-strong -fno-builtin-memcmp”,

 

“cxx” : “g++: g++ (Ubuntu 7.1.0-13ubuntu1) 7.1.0”,

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

“cxxflags” : “-g -O2 -fdebug-prefix-map=/build/mongodb-5gk9fl/mongodb-3.4.7=. -fstack-protector-strong -Wformat -Werror=format-security -Woverloaded-virtual -Wno-maybe-uninitialized -std=c++11”,

> db.runCommand({distinct:”Classes”,key:”ClassName”}).values

“linkflags” : “-Wl,-Bsymbolic-functions -Wl,-z,relro -pthread -Wl,-z,now -rdynamic -Wl,–fatal-warnings -fstack-protector-strong -fuse-ld=gold -Wl,–build-id -Wl,-z,noexecstack -Wl,–warn-execstack -Wl,-z,relro”,

[

“target_arch” : “x86_64”,

        “Class0”,

“target_os” : “linux”

        “Class1”,

},

        “Class2”,

“bits” : 64,

        “Class3”,

“debug” : false,

        “Class4”,

“maxBsonObjectSize” : 16777216,

        “Class5”,

“storageEngines” : [

        “Class6”,

“devnull”,

        “Class7”,

“ephemeralForTest”,

        “Class8”,

“mmapv1”,

        “Class9”

“wiredTiger”

]

],

>

“ok” : 1

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

}

 

 

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

2 collStats: 返回指定集合的统计信息,包括数据大小,已分配的存储空间和索引大小

语法:

> db.runCommand({“collStats”:”maple”})

db.runCommand({group:{

{

        ns:集合名字,

“ns” : “maple.maple”,

 Key:分组的键对象,

“size” : 234,

 Initial:初始化累加器,

“count” : 4,

 $reduce:组分解器,

“avgObjSize” : 58,

 Condition:条件,

“storageSize” : 36864,

 Finalize:组完成器

“capped” : false,

      }})

“wiredTiger” : {

 

“metadata” : {

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

“formatVersion” : 1

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

},

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

 

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

3 distinct:列出指定集合中满足查询条件的文档的指定键的所有不同值

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

> db.runCommand({“distinct”:”maple”,”key”:”name”})

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

{ “values” : [ “zhanghongfeng_maple” ], “ok” : 1 }

 

 

具体的使用可以参考手册:

4 drop和dropDatabase: 删除集合的所有数据和当前数据库的所有数据

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

5 getlastError: 查看对本集合执行的最后一次操作的错误信息或者其他状态信息。

 

6 isMaster: 检查本服务器是主服务器还是从服务器

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

> db.runCommand({“isMaster”:1})

var persons = [{

{

name:”Tom”,

“ismaster” : true,

age:25,

“maxBsonObjectSize” : 16777216,

country:”USA”

“maxMessageSizeBytes” : 48000000,

},

“maxWriteBatchSize” : 1000,

{

“localTime” : ISODate(“2017-12-27T13:45:21.228Z”),

name:”Jack”,

“maxWireVersion” : 5,

age:25,

“minWireVersion” : 0,

country:”USA”

“readOnly” : false,

},

“ok” : 1

{

}

name:”Lucy”,

7 Listcommands: 返回所有可以在服务器上运行的命令

age:26,

8 listDatabases:列出服务器上所有的数据库

country:”USA”

9 ping: 检测服务器的链接是否正常

},

> db.runCommand({“ping”:1})

{

{ “ok” : 1 }

name:”DaChengzi”,

10 

age:27,

 

country:”China”

固定集合:

},

顾名思义,固定集合就是能够将集合的大小以及文档数进行固定的集合。固定集合的创建方法是用createCollection。如下所示,size代表集合的大小,max代表最大的文档个数

{

> db.createCollection(“fixedcollection”,{capped:true,size:1000,max:2})

name:”Xiaojuz”,

{ “ok” : 1 }

age:26,

插入2个文档

country:”China”

>db.fixedcollection.insert({“name”:”zhanghongfeng”,”age”:33})

},

> db.fixedcollection.insert({“name”:”maple”,”age”:32})

{

显示插入的2个文档

name:”DaPingguo”,

> db.fixedcollection.find()

age:27,

{ “_id” : ObjectId(“5a43a73ba889535e61dc29a8”), “name” : “zhanghongfeng”, “age” : 33 }

country:”China”

{ “_id” : ObjectId(“5a43a77ba889535e61dc29a9”), “name” : “maple”, “age” : 32 }

},

再次插入一个文档

{

> db.fixedcollection.insert({“name”:”zhf”,”age”:32})

name:”XiaoBoluo”,

WriteResult({ “nInserted” : 1 })

age:27,

通过查询可以看到插入一个文档后,最早插入的文档name:zhanghongfeng被替换掉了。这是因为我们在创建固定集合指定了最大文档个数为2个。因此新插入的文档会替换之前的文档,替换方法是替换最早建立的文档。

country:”China”

> db.fixedcollection.find()

},

{ “_id” : ObjectId(“5a43a77ba889535e61dc29a9”), “name” : “maple”, “age” : 32 }

{

{ “_id” : ObjectId(“5a43a78ca889535e61dc29aa”), “name” : “zhf”, “age” : 32 }

name:”Bangzi1″,

固定集合的排列方式和环形队列一样,通过指定查询的顺序来查找,$natural:-1按照文档的插入时间从晚到早的顺序,也就是从队列的末尾开始查起。$natural:1是从队列的对头开始查起

age:26,

> db.fixedcollection.find().sort({“$natural”:-1})

country:”Korea”

{ “_id” : ObjectId(“5a43a78ca889535e61dc29aa”), “name” : “zhf”, “age” : 32 }

},

{ “_id” : ObjectId(“5a43a77ba889535e61dc29a9”), “name” : “maple”, “age” : 32 }

{

> db.fixedcollection.find().sort({“$natural”:1})

name:”LiShishi”,

{ “_id” : ObjectId(“5a43a77ba889535e61dc29a9”), “name” : “maple”, “age” : 32 }

age:27,

{ “_id” : ObjectId(“5a43a78ca889535e61dc29aa”), “name” : “zhf”, “age” : 32 }

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

}

插入完成后,查看一下:

图片 1

 

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

②访问网址

 

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”

        }

})

>

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

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

 

 

 

 

 

 

 

 

相关文章

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注