MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
       MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

目录

1.NOSQL分类

2.特点

3.数据模型

4.演示数据

5.基本概念

5.1 ACID VS BASE

5.2 SQL到Mongo映射

5.3文档

5.4 集合

5.5 固定集合

5.6 数据库

5.7 元数据

5.8 管道

5.9 数据类型

6. mongo维护

6.1 安装

6.2 启动/关闭

6.3 导入/导出

6.4 备份/恢复

6.5 数据修复/Fsnc锁

6.6 用户管理

6.7 常见命令

条件操作符

AND

OR

And & Or

in/nin

正则查询

Not

数组:all size slice .

内部文档

where


1.NOSQL分类

具体参考《一览NoSQL各种分类

2.特点

MongoDB特征

核心优势

灵活文档模型、高可用复制集、可拓展分片集群

功能特点

二级索引、地理位置索引、全文索引、aggregate、map-reduce、GridFs

不足之处

不支持事务、不支持表链接

3.数据模型

     一个MongoDB 实例可以包含一组数据库,一个DataBase 可以包含一组Collection(集合),一个集合可以包含一组Document(文档)。一个Document包含一组field(字段),每一个字段都是一个key/value pair。

key: 必须为字符串类型。

value:可以包含如下类型。

4.演示数据

var persons = [{

         name:"tom",

         age:25,

         email:"[email protected]",

         c:75,m:66,e:97,

         country:"USA",

         books:["PHP","JAVA","EXTJS","C++"]

},

{

         name:"lili",

         age:26,

         email:"[email protected]",

         c:75,m:63,e:97,

         country:"USA",

         books:["JS","JAVA","C#","MONGODB"]

},

{

         name:"zhangsan",

         age:27,

         email:"[email protected]",

         c:89,m:86,e:67,

         country:"China",

         books:["JS","JAVA","EXTJS","MONGODB"]

},

{

         name:"lisi",

         age:26,

         email:"[email protected]",

         c:53,m:96,e:83,

         country:"China",

         books:["JS","C#","PHP","MONGODB"]

},

{

         name:"zhaoliu",

         age:27,

         email:"[email protected]",

         c:99,m:96,e:97,

         country:"China",

         books:["JS","JAVA","EXTJS","PHP"]

},

{

         name:"lizhenxian",

         age:27,

         email:"[email protected]",

         c:35,m:56,e:47,

         country:"Korea",

         books:["JS","JAVA","EXTJS","MONGODB"]

},

{

         name:"lixiaoli",

         age:21,

         email:"[email protected]",

         c:36,m:86,e:32,

         country:"Korea",

         books:["JS","JAVA","PHP","MONGODB"]

},

{

         name:"zhangsuying",

         age:22,

         email:"[email protected]",

         c:45,m:63,e:77,

         country:"Korea",

         books:["JS","JAVA","C#","MONGODB"]

},

{

         name:"liuxiang",

         age:31,

         email:"[email protected]",

         c:99,m:96,e:97,

         country:"China",

         books:["JS","JAVA","EXTJS","VS"],

         address:{

                   city:"上海",

                   area:"普陀区XX路"

         }

},

{

         name:"chenlong",

         age:55,

         email:"[email protected]",

         c:99,m:96,e:97,

         country:"China",

         books:["JAVA","EXTJS","VS"],

         address:{

                   city:"香港",

                   area:"中环XX路"

         }

}]

for(var i = 0;i<persons.length;i++){

         db.persons.insert(persons[i])

}

5.基本概念

5.1 ACID VS BASE

在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (所有节点在同一时间具有相同的数据)
  • 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
  • 分区隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  • CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些

BASE:Basically Available, Soft-state, Eventually Consistent。由 Eric Brewer 定义。BASE是NoSQL数据库通常对可用性及一致性的弱要求原则:

  • Basically Availble --基本可用
  • Soft-state --软状态/柔性事务。 "Soft state" 可以理解为"无连接"的, 而 "Hard state" 是"面向连接"的
  • Eventual Consistency --最终一致性 最终一致性, 也是是 ACID 的最终目的。

ACID

BASE

原子性(Atomicity)

基本可用(Basically Available)

一致性(Consistency)

软状态/柔性事务(Soft state)

隔离性(Isolation)

最终一致性 (Eventual consistency)

持久性 (Durable)

 

5.2 SQL到Mongo映射

SQL术语/概念

MongoDB术语/概念

解释/说明

database

database

数据库

table

collection

数据库表/集合

row

document

数据记录行/文档

column

field

数据字段/

index

index

索引

table joins

 

表连接,MongoDB不支持(内嵌文档和链接)

primary key

primary key

主键,MongoDB自动将_id字段设置为主键

aggregation

 

Mongodb内置大量聚合管道

5.3文档

文档是 MongoDB 中数据的基本单位,类似于关系数据库中的行(但是比行复杂)

注意:

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

文档键命名规范:

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

5.4 集合

集合就是一组文档,类似于关系数据库中的表。集合是无模式的,集合中的文档可以是各式各样的。

注意:

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

5.5 固定集合

Capped collections 就是固定大小的collection。它有很高的性能以及队列过期的特性,collection的数据存储空间值提前分配的。

db.createCollection("mycoll", {capped:true, size:100000})

db.cappedLogCollection.isCapped()   --是否为固定集合

  • 插入速度极快
  • 插入顺序的查询输出速度极快
  • 能够在插入最新数据时,淘汰最早的数据
  • 能进行更新,但更新不能超出collection的大小,否则更新就会失败 。
  • 数据库不允许进行删除。使用drop()方法删除collection所有的行。删除之后,你必须显式的重新创建这个collection。
  • 在32位机子上一个cappped collection的最大值约为482.5M,64位上只受系统文件大小的限制

适用场景:

  • 存储日志信息
  • 缓存一些少量的文档

快速掌握mongodb入门手册

5.6 数据库

一个MongoDB 实例可以承载多个数据库。它们之间可以看作相互独立,每个数据库都有独立的权限控制。在磁盘上,不同的数据库存放在不同的文件中。MongoDB 中存在以下系统数据库。

  • Admin 数据库:一个权限数据库,如果创建用户的时候将该用户添加到admin 数据库中,那么该用户就自动继承了所有数据库的权限。
  • Local 数据库:这个数据库永远不会被负责,可以用来存储本地单台服务器的任意集合。
  • Config 数据库:当MongoDB 使用分片模式时,config 数据库在内部使用,用于保存分片的信息。

数据库名可以是满足以下条件的任意UTF-8字符串:

  • 不能是空字符串("")。
  • 不得含有' '(空格)、.、$、/、\和\0 (空宇符)。
  • 应全部小写。
  • 最多64字节

5.7 元数据

数据库的信息是存储在集合中。它们使用了系统的命名空间:已废弃

集合命名空间

描述

dbname.system.namespaces

列出所有名字空间。

dbname.system.indexes

列出所有索引。

dbname.system.profile

包含数据库概要(profile)信息。

dbname.system.users

列出所有可访问数据库的用户。

dbname.local.sources

包含复制对端(slave)的服务器信息和状态。

对于修改系统集合有如下限制。

  • {{system.indexes}}插入数据,可以创建索引。但除此之外该表信息是不可变的(特殊的drop index命令将自动更新相关信息)
  • {{system.users}}是可修改的。
  • {{system.profile}}是可删除的。

5.8 管道

管道在Linux中一般用于将当前命令的输出结果作为下一个命令的参数。MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

聚合框架中常用操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

5.9 数据类型

数据类型

描述

String

字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。

Integer

整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。

Boolean

布尔值。用于存储布尔值(真/假)。

Double

双精度浮点值。用于存储浮点值。

Min/Max keys

将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。

Arrays

用于将数组或列表或多个值存储为一个键。

Timestamp

时间戳。记录文档修改或添加的具体时间。

Object

用于内嵌文档。

Null

用于创建空值。

Symbol

符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。

Date

日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。

Object ID

对象 ID。用于创建文档的 ID

Binary Data

二进制数据。用于存储二进制数据。

Code

代码类型。用于在文档中存储 JavaScript 代码。

Regular expression

正则表达式类型。用于存储正则表达式。

6. mongo维护

数据库服务和客户端

mongod

类似mysqld

mongo

类似mysql/sqlplus         其实是个javascript引擎

mongoexport

导出命令

mongoimport

导入命令

mongotop

监控工具,跟踪数据库执行每个集合读写操作耗时

mongostat

监控工具,类似linux vmstat

mongos

路由工具(分片)

mongodump

数据备份

mongorestore

数据恢复

mongofiles

GridFS(添加文件)

mongoperf

独立检查mongoDBI/O性能的工具,类似linux iostat

mongooplog

用于从运行的mongod服务中拷贝运行日志到指定的服务器,主要用于增量备份

bsondump

用于将导出的BSON文件格式转换为JSON格式

mongosniff

(linuxunix有此工具)用于监控连接到mongodbTCP/IP连接,类似于tcpdump

6.1 安装

  1. 下载http://www.mongodb.org/downloads
  2. 设置环境变量path

6.2 启动/关闭

启动服务端:

  • mongod

参数

描述

--help

帮助

--bind_ip

绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP

--logpath

MongoDB日志文件,注意是指定文件不是目录

--logappend

使用追加的方式写日志

--dbpath

指定数据库路径

--port

指定服务端口号,默认端口27017

--serviceName

指定服务名称

--serviceDisplayName

指定服务名称,有多个mongodb服务时执行。

--install

指定作为一个Windows服务安装。

--auth

用安全认证方式启动

停止服务端:

  • ctrl+c 组合键可以关闭数据库
  • 进入admin数据库命令关闭数据 :db.shutdownServer()

启动客户端:

  • mongo

>Cd C:\

>mkdir mongodbdata

>mongod -dbpath C:\mongodbdata

>mongo --help

>mongo localhost:27017

>show dbs

>exit

>mongo 127.0.0.1:27017/admin  --admin身份进入

利用config配置文件来启动数据库改变端口为8888

mongodb.conf文件:

       dbpath = D:\sortware\mongod\db

       port = 8888

启动:

    mongod.exe --config ../mongodb.conf

6.3 导入/导出

1.导出数据(中断其他操作)

         -d 指明使用的库

         -c 指明要导出的表

         -o 指明要导出的文件名

         -csv 制定导出的csv格式

         -q 过滤导出

         --type <json|csv|tsv>      

mongoexport -d foobar -c persons -o D:/persons.json

mongoexport --host 192.168.0.16 --port 37017

2.导入数据(中断其他操作)

mongoimport --db foobar --collection persons --file d:/persons.json

6.4 备份/恢复

1.运行时备份mongodump

mongodump --host 127.0.0.1:27017 -d foobar -o d:/foobar

2.运行时恢复mongorestore

db.dropDatabase() --删除原本的数据库

mongorestore --host 127.0.0.1:27017 -d foobar -directoryperdb d:/foobar/foobar

3.懒人备份

      mongoDB是文件数据库这其实就可以用拷贝文件的方式进行备份

6.5 数据修复/Fsnc锁

1.Fsync的使用

快速掌握mongodb入门手册

2.上锁和解锁      

db.runCommand({fsync:1,lock:1})          --上锁       

db.currentOp()        --解锁

3.数据修复

         当停电等不可逆转灾难来临的时候,由于mongodb的存储结构导致会产生垃圾数据,在数据恢复以后这垃圾数据依然存在,这是数据库提供一个自我修复的能力.使用起来很简单

db.repairDatabase()

6.6 用户管理

远程mongo 192.168.2.203:27017/gesb -ureaduser -pJcizexRo4

mongo localhost:27017/admin

show roles

 

use test

db.createUser(

  {

    user: "alex",

    pwd: "123",

    roles: [ { role: "__system", db: "admin" } ]

  }

)

mongod -dbpath C:\mongodbdata --rest –auth      --cmd

db.auth("alex","123")

db.dropUser(“alex”)

db.runCommand({usersInfo:1})       --all users

db.system.users.find().pretty()       --use admin

6.7 常见命令

  • show dbs/show tables/show users
  • db.getCollectionNames()
  • db.version()
  • db.hostInfo()
  • db.stats()          -- db 的元数据信息
  • db.serverStatus()
  • rs.conf()               --副本集
  • rs.status()             --副本集
  • rs.reconfig()                 --副本集
  •  

 

  1. 数据库操作

 

 

    1. 服务端脚本

1.Eval

db.eval("function(name){ return name}","uspcat")

2.Javascript的存储(服务上保存js变量活着函数共全局调用)

db.system.js.insert({_id:name,value:”uspcat”})     --加载到特殊集合system.js

db.eval("return  name;")

System.js相当于Oracle中的存储过程,因为value不单单可以写变量还可以写函数体也就是javascript代码

 

 

    1. 新建

use test                               ---新建test db(若不执行insert,数据库不会被创建)

db.person.insert({name:"mongodb"})

db.person.find()

db

show dbs

 

 

 

    1. 删除

use test

db.dropDatabase()

show dbs

 

 

 

    1. runCommand

runCommand可以执行mongoDB中的特殊函数,

用命令执行完成一次删除表的操作

                   db.runCommand({drop:"map"})

                   {

                                     "nIndexesWas" : 2,

                                     "msg" : "indexes dropped for collection",

                                     "ns" : "foobar.map",

                                     "ok" : 1

                   }

查询服务器版本号和主机操作系统

db.runCommand({buildInfo:1})

查询执行集合的详细信息,大小,空间,索引等……

db.runCommand({collStats:"persons"})

查看操作本集合最后一次错误信息

db.runCommand({getLastError:"persons"})

 

 

 

 

    1. findAndModify

findAndModify就是特殊函数之一他的用于是返回update或remove后的文档

runCommand({“findAndModify”:”processes”,

         query:{查询器},

                   sort{排序},

                   new:true

                   update:{更新器},

                   remove:true

           ).value

 

ps = db.runCommand({

        "findAndModify":"persons",

        "query":{"name":"text"},

                   "update":{"$set":{"email":"1221"}},

                   "new":true

}).value

do_something(ps)

 

 

 

 

  1. 文档操作

show tables

 

 

    1. 文档插入

 

 

      1. 插入

db.[documentName].insert(document)

 

 

      1. 批量插入

shell 这样执行是错误的 db.[documentName].insert([{},{},{},……..]),shell 不支持批量插入

想完成批量插入可以用mongo的应用驱动或是shell的for循环

> function batch(){

... for(var i=0;i<5;i++){

... db.persons.insert({name:"person"+i})

... }}

> batch()

 

 

 

 

      1. save

save操作和insert操作区别在于当遇到_id相同的情况下,save完成保存操作,          insert则会报错

 

 

    1. 文档删除

db.[documentName].remove(

   <query>,

     {

             justOne: <boolean>,

             writeConcern: <document>

}

)

  1. query :(可选)删除的文档的条件。
  2. justOne : (可选)如果设为 true 或 1,则只删除一个文档。
  3. writeConcern :(可选)抛出异常的级别。

 

小技巧:

  • 集合的本身和索引不会被删除
  • 如果你想清楚一个数据量十分庞大的集合,直接删除该集合并且重新建立索引的办法,比直接用remove的效率和高很多

 

 

    1. 文档更新

db.[documentName].update(

   <query>,

   <update>,

   {

     upsert: <boolean>,

     multi: <boolean>,

     writeConcern: <document>

   }

)

  1. query : update的查询条件,类似sql update查询内where后面的。
  2. update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  3. upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。--insertOrUpdate
  4. multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。--批量更新操作
  5. writeConcern :可选,抛出异常的级别。

快速掌握mongodb入门手册

快速掌握mongodb入门手册

$addToSet与$each结合完成批量数组更新

db.text.update({_id:1000},{$addToSet:{books:{$each:[“JS”,”DB”]}}})

 

注意:存在分配与查询效率

当document被创建的时候DB为其分配没存和预留内存当修改操作,不超过预留内层的时候则速度非常快反而超过了就要分配新的内存则会消耗时间

快速掌握mongodb入门手册

 

db.persons.update({name:"person1"},{$set:{name:"pp"}})

db.[documentName].update({查询器},{修改器},true)

db.[documentName].update({查询器},{修改器},false, true)

 

 

 

 

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

db.createCollection("mycoll",{size:100,capped:true,max:10})

  • 把一个普通集合转换成固定集合

db.runCommand({convertToCapped:”persons”,size:100000})

  • 查询固定集合mycoll并且反向排序(默认是插入顺序排序)

db.mycoll.find().sort({$natural:-1})

  • 尾部游标概念(可惜shell不支持java和php等驱动是支持的)

这是个特殊的只能用到固定级和身上的游标,他在没有结果的时候,也不回自动销毁他是一直等待结果的到来

 

 

    1. 数据模型校验器

文档格式太灵活也会有问题的,不便于维护

http://www.cnblogs.com/sjjsxl/p/5126313.html

 

db.createCollection( "contacts",

   {

      validator: { $or:

         [

            { phone: { $type: "string" } },

            { email: { $regex: /@mongodb\.com$/ } },

            { status: { $in: [ "Unknown", "Incomplete" ] } }

         ],

       validationAction: "warn"

      }

   }

)

 

db.contacts.insert( { name: "Amanda", status: "Updated" } )

 

--添加一个验证器

db.runCommand( {

   collMod: "contacts",

   validator: { $or: [ { phone: { $exists: true } }, { email: { $exists: true } } ] },

   validationLevel: "moderate"

} )

 

 

 

  1. 数据检索

 

 

    1. Find/pretty

db.persons.find().pretty()        ---结构化的方式来显示

db.persons.find ({条件},{键指定})

db.persons.find({}, {

         name : 1,

         age : 1,

         country : 1,

         _id : 0

})

条件操作符

操作

范例

RDBMS中的类似语句

等于

db.persons.find({"name":"lixiaoli"})

where by = 'lixiaoli'

小于

db.persons.find({"age":{$lt:25}})

where age< 25

小于或等于

db.persons.find({"age":{$lte:25}})

where age<= 25

大于

db.persons.find({"age":{$gt:25}})

where age> 25

大于或等于

db.persons.find({"age":{$gte:25}})

where age>= 25

不等于

db.persons.find({"age":{$ne:25}})

where age!= 25

AND

传入多个键(key),每个键(key)以逗号隔开,及常规 SQL 的 AND 条件

db.persons.find({

         name : "lixiaoli",

         country : "Korea"

}).pretty()

OR

条件语句使用了关键字 $or

db.persons.find({

         $or : [{

                            "name" : "lixiaoli"

                   }, {

                            "age" : 25

                   }

         ]

}).pretty()

 

And & Or

db.persons.find({

         "country" : "USA",

         $or : [{

                            "name" : "lixiaoli"

                   }, {

                            "age" : 25

                   }

         ]

}).pretty()

in/nin

db.persons.find({

         country : {

                   $in : ["USA", "China"]

         }

})

 

db.persons.find({

         country : {

                   $nin : ["USA", "China"]

         }

})

 

正则查询

db.persons.find({

         name : /li/i

}, {

         _id : 0,

         name : 1

})

 

Not

取反操作, 查询出名字中不存在”li”的学生

db.persons.find({

         name : {

                   $not : /li/i

         }

}, {

         _id : 0,

         name : 1

})

$not和$nin的区别是$not可以用在任何地方儿$nin是用到集合上的

 

数组:all size slice .

$all对数组内元素的顺序没有要求

db.persons.find({

         "books" : {

                   $all : ["JS","JAVA"]

         }

})

. 数组索引从0开始(查询第二本书是JAVA的学习信息)

db.persons.find({

         "books.1" : "JAVA"

}, {

         books : 1

})

$size条件操作符,查询数组长度

db.persons.find({

         "books" : {

                   $size : 4

         }

}, {

         books : 1

})

$slice数组截取,用复数即可,如-1表明截取最后一个;如[2,3],即跳过前两个,截取3个,如果剩余不足3个,就全部返回!

db.persons.find({}, {

         books : {

                   $slice : [1, 3]

         }

})

 

小技巧:喜欢的书籍数量大于3本的学生?

1.增加字段size

db.persons.update({},{$set:{size:4}},false, true)

2.改变书籍的更新方式,每次增加书籍的时候size增加1

db.persons.update({查询器},{$push:{books:”ORACLE”},$inc:{size:1}})

3.利用$gt查询

db.persons.find({size:{$gt:3}})

 

内部文档

查询出在K上过学的学生(问题:顺序?全部匹配?)

db.persons.find({

         "address" : {

                   "city" : "上海",

                   "area" : "普陀区XX路"

         }

})

为了解决上面顺序的问题用对象”.”的方式定位

db.persons.find({

         "address.city" : "香港",

         "address.area" : "中环XX路"

})

可能是版本问题,如果上面有问题请使用$elemMatch吧

where

复杂的查询我们就可以用$where因为它是万能,但是我们要尽量避免少使用它因为他会有性能的代价

 

 

小结

        shell是个彻彻底底的JS引擎,但是一些特殊的操作要靠他的各个驱动包来完成(JAVA,NODE.JS)

 

 

    1. Limit/skip/sort

db.persons.find({}).limit(2)

查询2~7条的数据

db.persons.find({}).limit(5).skip(2)

排序的数据[1,-1]

db.persons.find({}, {

         name : 1,

         age : 1

}).sort({

         age : 1

})

注意:

  • mongodb的key可以存不同类型的数据排序就也有优先级

最小值>null>数字>字符串>对象/文档>数组>二进制>对象ID>布尔>日期>时间戳 >正则>最大值

  • skip有性能问题,

没有特殊情况下我们也可以换个思路,每次查询操作的时候前后台传值全要把上次的最后一个文档的日期保存下来,db.persons.find({date:{$gt:日期数值}}).limit(3)

 

 

    1. Count

请查询persons中美国学生的人数.

db.persons.find({country:"USA"}).count()

 

 

    1. Distinct

请查询出persons中一共有多少个国家分别是什么.

db.runCommand({

         distinct : "persons",

         key : "country"

}).values

 

 

    1. Group

请查出persons中每个国家学生数学成绩最好的学生信息(必须在90以上)

db.runCommand({group:{

         ns:"persons",

         key:{"country":true},

         initial:{m:0},

         $reduce:function(doc,prev){

                   if(doc.m > prev.m){

                            prev.m = doc.m;

                            prev.name = doc.name;

                            prev.country = doc.country;

                   }

         },

         condition:{m:{$gt:90}}

}})

 

把个人的信息链接起来写一个描述赋值到m上

finalize:function(prev){

prev.m = prev.name+" Math scores "+prev.m

}

如果集合中出现键Counrty和counTry同时存在那分组有点麻烦这要如何解决呢?

db.runCommand({group:{

         ns:"persons",

         $keyf:function(doc){

                   if(doc.counTry){

                            return {country:doc.counTry}

                   }else{

                            return {country:doc.country}

                   }

         },

         initial:{m:0},

         $reduce:function(doc,prev){

                   if(doc.m > prev.m){

                            prev.m = doc.m;

                            prev.name = doc.name;

                            if(doc.country){

                                     prev.country = doc.country;

                            }else{

                                     prev.country = doc.counTry;

                            }

                   }

         },

         finalize:function(prev){

                   prev.m = prev.name+" Math scores "+prev.m

         },

         condition:{m:{$gt:90}}

}})

 

 

    1. 聚合

主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果

db.persons.aggregate([{

                            $group : {

                                     _id : "$country",

                                     total_num : {

                                               $sum : 1

                                     }

                            }

                   }

         ])

表达式

描述

实例

$sum

计算总和。

db. persons.aggregate([{$group : {_id : "$country",total_num : {$sum : "$age"}}}])

$avg

计算平均值

db. persons.aggregate([{$group : {_id : "$country",total_num : {$avg : "$age"}}}])

$min

获取集合中所有文档对应值得最小值。

db. persons.aggregate([{$group : {_id : "$country", total_num : {$min : "$age"}}}])

$max

获取集合中所有文档对应值得最大值。

db. persons.aggregate([{$group : {_id : "$country", total_num : {$max : "$age"}}}])

$push

在结果文档中插入值到一个数组中。

db. persons.aggregate([{$group : {_id : "$country", names : {$push: "$name"}}}])

$addToSet

在结果文档中插入值到一个数组中,但不创建副本。

db. persons.aggregate([{$group : {_id : "$country", names: {$addToSet : "$name"}}}])

$first

根据资源文档的排序获取第一个文档数据。

db. persons.aggregate([{$group : {_id : "$country", first_name : {$first : "$name"}}}])

$last

根据资源文档的排序获取最后一个文档数据

db. persons.aggregate([{$group : {_id : "$country", last_name : {$last : "$name"}}}])

 

管道操作(参考管道5.8)

db.persons.aggregate(

    { $project : {

        name : 1 ,

        country : 1 ,

    }}

 )

获取年龄大于20小于或等于50记录,然后将结果集再送到$group管道操作符进行处理

db.persons.aggregate([{

                            $match : {

                                     age : {

                                               $gt : 20,

                                               $lte : 50

                                     }

                            }

                   }, {

                            $group : {

                                     _id : "country",

                                     count : {

                                               $sum : 1

                                     }

                            }

                   }

         ])

 

 

    1. 游标

var persons = db.persons.find();

while (persons.hasNext()) {

         obj = persons.next();

         print(obj.name)

}

游标销毁条件

  1. 客户端发来信息叫他销毁
  2. 游标迭代完毕
  3. 默认游标超过10分钟没用也会别清除

 

 

    1. 快照

为什么要用查询快照?

快速掌握mongodb入门手册

快照后就会针对不变的集合进行游标运动了,看看使用方法.

db.persons.find({

         $query : {

                   name : "lixiaoli"

         },

         $snapshot : true

})

高级查询选项

$query

$orderby

$maxsan:integer 最多扫描的文档数

$min:doc  查询开始

$max:doc  查询结束

$hint:doc   使用哪个索引

$explain:boolean  统计

$snapshot:boolean 一致快照

 

 

 

    1. $type

$type操作符是基于BSON类型来检索集合中匹配的数据类型

类型

数字

备注

Double

1

 

String

2

 

Object

3

 

Array

4

 

Binary data

5

 

Undefined

6

已废弃。

Object id

7

 

Boolean

8

 

Date

9

 

Null

10

 

Regular Expression

11

 

JavaScript

13

 

Symbol

14

 

JavaScript (with scope)

15

 

32-bit integer

16

 

Timestamp

17

 

64-bit integer

18

 

Min key

255

Query with -1.

Max key

127

 

db.persons.find({

         "name" : {

                   $type : 2

         }

})

 

 

  1. MapReduce

Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。

db.collection.mapReduce(

   function() {emit(key,value);},  //map 函数

   function(key,values) {return reduceFunction},   //reduce 函数

   {

      out: collection,

      query: document,

      sort: document,

      limit: number

   }

)

Map 函数必须调用 emit(key, value) 返回键值对。

参数说明:

  • map :映射函数 (生成键值对序列,作为 reduce 函数参数)。
  • reduce 统计函数,reduce函数的任务就是将key-values变成key-value,也就是把values数组变成一个单一的值value。。
  • out 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
  • query 一个筛选条件,只有满足条件的文档才会调用map函数。(query。limit,sort可以随意组合)
  • sort 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制
  • limit 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)

 

 

  1. 索引

 

 

    1. 索引详解

 

for(var i = 0 ; i<20000 ;i++){

         db.books.insert({number:i,name:i+"book"})

}

db.books.ensureIndex({number:1})

db.books.ensureIndex({name:-1},{name:”bookname”}) --指定索引名称

db.books.ensureIndex({name:-1},{unique:true})

db.books.ensureIndex({name:-1},{unique:true,dropDups:true})  --踢出重复值

db.books.ensureIndex({name:-1},{background:true})

 

db.system.indexes.find()          已废弃

db.persons.getIndexes()

db.persons.reIndex()

db.persons.dropIndex(“bookname”)

db.persons.dropIndexes()

 

 

注意:

  • 创建索引的时候注意1是正序创建索引-1是倒序创建索引
  • 索引的创建在提高查询性能的同事会影响插入的性能
  • 对于经常查询少插入的文档可以考虑用索引
  • 索引不是万能的,每个键全建立索引不一定就能提高性能
  • 在做排序工作的时候如果是超大数据量也可以考虑加上索引
  • 执行创建索引的过程会暂时锁表问题

索引限制:

索引不能被以下的查询使用:

  • 正则表达式及非操作符,如 $nin, $not, 等。
  • 算术运算符,如 $mod, 等。
  • $where 子句

所以,检测你的语句是否使用索引是一个好的习惯,可以用explain来查看。

最大范围

  • 集合中索引不能超过64个
  • 索引名的长度不能超过125个字符
  • 一个复合索引最多可以有31个字段
  • 从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。

Parameter

Type

Description

background

Boolean

建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false

unique

Boolean

建立的索引是否唯一。指定为true创建唯一索引。默认值为false.

name

string

索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。

dropDups

Boolean

在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.

sparse

Boolean

对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.

expireAfterSeconds

integer

指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。

v

index version

索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。

weights

document

索引权重值,数值在 1 99,999 之间,表示该索引相对于其他索引字段的得分权重。

default_language

string

对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语

language_override

string

对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

 

 

 

      1. Hint

强制查询使用指定的索引,但是必须已经创建了的索引

db.books.find({name:"1book",number:1}).hint({name:-1})

 

 

 

      1. Explain

db.books.find({name:"1book"}).explain()

  • indexOnly: 字段为 true ,表示我们使用了索引
  • cursor:索引的名称,因为这个查询使用了索引,所以这是也使用了BtreeCursor类型的游标。如果没有使用索引,游标的类型是BasicCursor
  • indexBounds:当前查询具体使用的索引。
  • nscanned/nscannedObjects:表明当前这次查询一共扫描了集合中多少个文档
  • millis: 当前查询所需时间,毫秒数。
  • n:当前查询返回的文档数量

 

 

 

    1. 联合索引

 

 

    1. 索引数组

 

 

    1. 索引子文档

 

 

    1. 空间索引

mongoDB提供强大的空间索引可以查询出一定范围的地理坐标.看例子

快速掌握mongodb入门手册

添加2D索引,默认会建立一个[-180,180]之间的2D索引

db.map.ensureIndex({"gis":"2d"},{min:-1,max:201})

1.查询出距离点(70,180)最近的3个点

db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)

2.查询以点(50,50)和点(190,190)为对角线的正方形中的所有的点

db.map.find({gis:{"$within":{$box:[[50,50],[190,190]]}}},{_id:0,gis:1})

3.查询出以圆心为(56,80)半径为50规则下的圆心面积中的点

db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})

 

测试数据:

var map=[{"gis":{"x":185,"y":150}},{"gis":{"x":70,"y":180}},{"gis":{"x":75,"y":180}},{"gis":{"x":185,"y":185}},{"gis":{"x":65,"y":185}},{"gis":{"x":50,"y":50}},{"gis":{"x":50,"y":50}},{"gis":{"x":60,"y":55}},{"gis":{"x":65,"y":80}},{"gis":{"x":55,"y":80}},{"gis":{"x":0,"y":0}},{"gis":{"x":0,"y":200}},{"gis":{"x":200,"y":0}},{"gis":{"x":200,"y":200}}]

for(var i = 0;i<map.length;i++){

         db.map.insert(map[i])

}

 

 

  1. GridFS

GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。

GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档。

GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。

  • 利用mongoVUE
  • 利用后台命令

mongofiles.exe -d gridfs put c:\a.txt                 --cmd

mongofiles -d gridfs list                                        --cmd

mongofiles -d gridfs delete "a.txt"                    --cmd

use gridfs

db.fs.files.find().pretty()

db.fs.chunks.find({files_id:ObjectId("583e8e25858ded1b343034cc")}).pretty()

 

 

 

  1. 集群

 

 

    1. 复制

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。常见的搭配方式为:一主一从、一主多从,主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

特征:

  • N个节点的集群
  • 任何节点可作为主节点
  • 所有写入操作都在主节点上
  • 自动故障转移
  • 自动恢复

db.isMaster()

 

 

      1. 主从复制

8888.conf:

dbpath = D:\software\MongoDBDATA\07\8888   #主数据库地址

port = 8888 #主数据库端口号

bind_ip = 127.0.0.1 #主数据库所在服务器

master = true #确定我是主服务器

7777.conf:

dbpath = D:\software\MongoDBDATA\07\7777   #从数据库地址

port = 7777 #从数据库端口号

bind_ip = 127.0.0.1 #从数据库所在服务器

source = 127.0.0.1:8888 #确定我数据库端口,这个配置项(source)可以用shell动态添加

slave = true #确定自己是从服务器

 

mongod --config 7777.conf

mongod --config 8888.conf

mongo 127.0.0.1:7777

mongo 127.0.0.1:8888

 

2.主从复制的其他设置项

--only  从节点指定复制某个数据库,默认是复制全部数据库

--slavedelay  从节点设置主数据库同步数据的延迟(单位是秒)

--fastsync 从节点以主数据库的节点快照为节点启动从数据库

--autoresync 从节点如果不同步则从新同步数据库

--oplogSize  主节点设置oplog的大小(主节点操作记录存储到local的oplog中)

3.利用shell动态添加和删除从节点

快速掌握mongodb入门手册

不难看出从节点中关于主节点的信息全部存到local的sources的集合中

我们只要对集合进行操作就可以动态操作主从关系

挂接主节点:操作之前只留下从数据库服务

db.sources.insert({“host”:”127.0.0.1:8888”})

删除已经挂接的主节点:操作之前只留下从数据库服务

db.sources.remove({“host”:”127.0.0.1:8888”})

 

 

 

      1. 副本集

快速掌握mongodb入门手册

1.副本集概念

当A出现了故障,这时候集群根据权重算法推选出B为活跃的数据库,当A恢复后他自动又会变为备份数据库

A.conf:

dbpath = D:\sortware\mongod\02\A

port = 1111  #端口

bind_ip = 127.0.0.1 #服务地址

replSet = child/127.0.0.1:2222 #设定同伴

B.conf:

dbpath = D:\sortware\mongod\02\B

port = 2222

bind_ip = 127.0.0.1

replSet = child/127.0.0.1:3333

C.conf:

dbpath = D:\sortware\mongod\02\C

port = 3333

bind_ip = 127.0.0.1

replSet = child/127.0.0.1:1111

 

2.初始化副本集

use admin

db.runCommand({"replSetInitiate":

   {

      "_id":'child',

       "members":[{

                 "_id":1,

                   "host":"127.0.0.1:1111"

             },{

                   "_id":2,

                   "host":"127.0.0.1:2222"

             },{

                   "_id":3,

                   "host":"127.0.0.1:3333"

             }]

    }

})

2.查看副本集状态

rs.status()

3.节点和初始化高级参数

      1. standard常规节点:参与投票有可能成为活跃节点
      2. passive副本节点:参与投票,但是不能成为活跃节点
      3. arbiter仲裁节点:只是参与投票不复制节点也不能成为活跃节点

4.高级参数

Priority  0到1000之间 ,0代表是副本节点 ,1到1000是常规节点

arbiterOnly : true 仲裁节点

用法

members":[{

"_id":1,

"host":"127.0.0.1:1111“,

arbiterOnly : true

}]”

5.优先级相同时候仲裁组建的规则(B优先)

 

A

优先级1

B

优先级1

C

优先级1

5秒前更新

1秒前更新

 

 

 

 

 

6.读写分离操作扩展读

  • 一般情况下作为副本的节点是不能进行数据库读操作的,但是在读取密集型的系统中读写分离是十分必要的
  • 设置读写分离(slaveOkay :  true),很遗憾他在shell中无法演示,这个特性是被写到mongoDB的驱动程序中的,在java和node等其他语言中可以完成

7.Oplog

  • 他是被存储在本地数据库local中的,他的每一个文档保证这一个节点操作

     如果想故障恢复可以更彻底oplog可已经尽量设置大一些用来保存更多的操作信息

     改变oplog大小

     主库 --master --oplogSize  size

    1. 分片

1.插入负载技术(图1)

2.片键的概念和用处(利用key为片键进行自动分片)(图2)

3.什么时候用到分片呢?

  • 机器的磁盘空间不足
  • 单个的mongoDB服务器已经不能满足大量的插入操作
  • 想通过把大数据放到内存中来提高性能

4.分片步骤

  • 4.1创建一个配置服务器
  • 4.2创建路由服务器,并且连接配置服务器

路由器是调用mongos命令

  • 4.3添加2个分片数据库

8081和8082

  • 4.5利用路由为集群添加分片(允许本地访问)

db.runCommand({addshard:"127.0.0.1:8081",allowLocal:true})

db.runCommand({addshard:"127.0.0.1:8081",allowLocal:true})

切记之前不能使用任何数据库语句

  • 4.6打开数据分片功能,为数据库foobar打开分片功能

db.runCommand({"enablesharding":"foobar"})

  • 4.7对集合进行分片

db.runCommand({"shardcollection":"foobar.bar","key":{"_id":1}})

  • 4.8利用大数据量进行测试 (800000条)

5.查看配置库对于分片服务器的配置存储

db.printShardingStatus()

6.查看集群对bar的自动分片机制配置信息

mongos> db.shards.find()

{ "_id" : "shard0000", "host" : "127.0.0.1:8081" }

{ "_id" : "shard0001", "host" : "127.0.0.1:8082" }

7.保险起见的通常配置服务器做集群

8.分片与副本集一起使用(图3)

 

快速掌握mongodb入门手册

快速掌握mongodb入门手册快速掌握mongodb入门手册

 

  1. 管理工具

 

 

    1. MongoVUE

 

 

    1. RockMongo

 

 

x

相关文章: