mongodb学习笔记

Posted 阿征new

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb学习笔记相关的知识,希望对你有一定的参考价值。

mongodb


memcached

redis        kv数据库(key/value)

 

mongodb 文档数据库,存储的是文档(Bson->json的二进制化).

 

特点:内部执行引擎为JS解释器,把文档存储成bson结构,在查询时,转换为JS对象,并可以通过熟悉的js语法来操作.

 

mongo和传统型数据库相比,最大的不同:

传统型数据库: 结构化数据,定好了表结构后,每一行的内容,必是符合表结构的,就是说--列的个数,类型都一样.

mongo文档型数据库:表下的每篇文档,都可以有自己独特的结构(json对象都可以有自己独特的属性和值)

 

思路: 如果有电影,影评,影评的回复,回复的打分

在传统型数据库中, 至少要4张表,关联度非常复杂.

在文档数据库中,通过1篇文档,即可完成.  体现出文档型数据库的反范式化.

{

 fiim:’天龙八部’

 comment:[

{content:’王家卫的电影风格’,

 reply:[‘支持’,’好’]

}

]

}


mongodb的安装

1: 下载mongodbwww.mongodb.org  下载最新的stable

2: 解压文件

3: 不用编译,本身就是编译后的二进制可执行文件.

 

4: 启动mongod服务

./bin/mongod --dbpath /path/to/database --logpath /path/to/log --fork --port 27017

参数解释:

--dbpath 数据存储目录

--logpath 日志存储目录

--port 运行端口(默认27017)

--fork 后台进程运行


5: mongodb非常的占磁盘空间,刚启动后要占3-4G左右,

如果你用虚拟机练习,可能空间不够,导致无法启动.

可以用 --smallfiles 选项来启动,

将会占用较小空间  400M左右.

 

1: mongo入门命令

 

1.1: show dbs  查看当前的数据库

1.2 use databaseName 选库

1.2 show tables/collections 查看当前库下的collection


1.3 如何创建库?

Mongodb的库是隐式创建,你可以use一个不存在的库

然后在该库下创建collection,即可创建库

 

1.4 db.createCollection(‘collectionName’)  

创建collection

 

1.5 collection允许隐式创建

Db.collectionName.insert(document);

 

1.6 db.collectionName.drop() ,

删除collection

 

1.7 db.dropDatabase();

删除database

 

基本操作增删改查

: insert

介绍: mongodb存储的是文档,.文档是json格式的对象.

 

语法: db.collectionName.isnert(document);

 

1: 增加单篇文档

Db.collectionName.insert({title:’nice day’});

 

2: 增加单个文档,并指定_id

Db.collectionName.insert({_id:8,age:78,name:’lisi’});

 

3. 增加多个文档

db.collectionName.insert(

[

{time:‘friday‘,study:‘mongodb‘},

{_id:9,gender:‘male‘,name:‘QQ‘}

]

)


:remove

语法: db.collection.remove(查询表达式,选项);

选项是指  {justOne:true/false},是否只删一行,默认为false

 

注意

1: 查询表达式依然是个json对象

2: 查询表达式匹配的行,将被删掉.

3: 如果不写查询表达式,collections中的所有文档将被删掉.

 

1: db.stu.remove({sn:’001’});

删除stu表中sn属性值为’001’的文档

 

2: db.stu.remove({gender:’m’,true});

删除stu表中gender属性为m的文档,只删除1.

 

改  update操作

改谁? --- 查询表达式

改成什么样? -- 新值 或 赋值表达式

操作选项 ----- 可选参数

 

语法: db.collection.update(查询表达式,新值,选项);

例:

db.news.update({name:‘QQ‘},{name:‘MSN‘});

是指选中news表中,name值为QQ的文档,并把其文档值改为{name:’MSN’},

结果:文档中的其他列也不见了,改后只有_idname列了.

--新文档直接替换了旧文档,而不是修改

 

如果是想修改文档的某列,可以用$set关键字

db.collectionName.update(query,{$set:{name:’QQ’}})

 

修改时的赋值表达式

$set  修改某列的值

$unset 删除某个列

$rename 重命名某个列

$inc 增长某个列

$setOnInsert upserttrue,并且发生了insert操作时,可以补充的字段.

 

Option的作用:

{upsert:true/false,multi:true/false}

Upsert---是指没有匹配的行,则直接插入该行.(mysql中的replace一样)

 

:db.stu.update({name:‘wuyong‘},{$set:{name:‘junshiwuyong‘}},{upsert:true});

如果有name=’wuyong’的文档,将被修改

如果没有,将添加此新文档

:

db.news.update({_id:99},{x:123,y:234},{upsert:true});

没有_id=99的文档被修改,因此直接插入该文档

multi: 是指修改多行(即使查询表达式命中多行,默认也只改1,如果想改多行,可以用此选项)

:

db.news.update({age:21},{$set:{age:22}},{multi:true});

则把news中所有age=21的文档,都修改

 

: find, findOne

语法: db.collection.find(查询表达式,查询的列);

Db.collections.find(表达式,{1:1,2:1});

1:db.stu.find()

查询所有文档 所有内容

2: db.stu.find({},{gendre:1})

查询所有文档,gender属性(_id属性默认总是查出来)

3: db.stu.find({},{gender:1, _id:0})

查询所有文档的gender属性,且不查询_id属性

3: db.stu.find({gender:’male’},{name:1,_id:0});

查询所有gender属性值为male的文档中的name属性

pretty() 方法

结果显示在一个格式化的方式,可以使用 pretty() 方法.

语法:

>db.mycol.find().pretty()

例子

>db.mycol.find().pretty(){

   "_id": ObjectId(7df78ad8902c),

   "title": "MongoDB Overview", 

   "description": "MongoDB is no sql database",

   "by": "tutorials yiibai",

   "url": "http://www.yiibai.com",

   "tags": ["mongodb", "database", "NoSQL"],

   "likes": "100"}>


查询表达式:

 

1: 最简单的查询表达式

{filed:value} ,是指查询field列的值为value的文档

2: $ne --- != 查询表达式

{field:{$nq:value}}

作用--filed列的值不等于 value的文档

3: $nin --> not in

4: $all

语法: {field:{$all:[v1,v2..]}}

是指取出 field列是一个数组,且至少包含v1,v2

5: $exists

语法: {field:{$exists:1}}

作用: 查询出含有field字段的文档

6: $nor,

{$nor,[条件1,条件2]}

是指  所有条件都不满足的文档为真返回

7:用正则表达式查询 以”诺基亚”开头的商品

:db.goods.find({goods_name:/诺基亚.*/},{goods_name:1});

8: $where表达式来查询

: db.goods.find({$where:‘this.cat_id != 3 && this.cat_id != 11‘});

 

注意: $where查询时, mongodb是把bson结构的二进制数据转换为json结构的对象,

然后比较对象的属性是否满足表达式.


速度较慢

 

Update时可用的操作符

:

->db.user.insert({name:‘lisi‘,age:12,sex:‘male‘,height:123,area:‘haidian‘});

->db.user.update({name:‘lisi‘},{$set:{area:‘chaoyang‘},$unset:{height:1},$inc:{age:1},$rename:{sex:‘gender‘}});

> db.user.find();

{ "_id" : ObjectId("51fc01c4f5de93e1f2856e33"), "age" : 13, "area" : "chaoyang", "gender" : "male", "name" : "lisi" }

 

$setOnInsert ->相当于mysql中的列的默认值

 

游标操作   cursor

 

游标是什么\?

通俗的说,游标不是查询结果,而是查询的返回资源,或者接口.

通过这个接口,你可以逐条读取.

就像php中的fopen打开文件,得到一个资源一样,通过资源,可以一行一行的读文件.

 

声明游标:

var cursor =  db.collectioName.find(query,projection);

Cursor.hasNext() ,判断游标是否已经取到尽头

Cursor. Next() , 取出游标的下1个单元


while来循环游标

> var mycursor = db.bar.find({_id:{$lte:5}})

> while(mycursor.hasNext()) {

... printjson(mycursor.next());

... }

 

:

// 声明游标

var cursor = db.goods.find();

// 循环游标

for(var doc=true;cursor.hasNext();) { printjson(cursor.next());}

 

也可以简写:

for(var  cursor=db.goods.find(), doc=true;cursor.hasNext();) { printjson(cursor.next());}

 

游标还有一个迭代函数,允许我们自定义回调函数来逐个处理每个单元.

cursor.forEach(回调函数);

:

> var gettitle = function(obj) {print(obj.goods_name)}

> var cursor = db.goods.find();

> cursor.forEach(gettitle);


游标在分页中的应用

比如查到10000,跳过100,10.

一般地,我们假设每页N,当前是page

就需要跳过前 (page-1)*N ,再取N,mysql, limit offset,N来实现

mongo,skip(), limit()函数来实现的

 

var mycursor = db.bar.find().skip(9995);

则是查询结果中,跳过前9995

 

查询第901,每页10

则是 var mytcursor = db.bar.find().skip(9000).limit(10);

 

通过cursor一次性得到所有数据,并返回数组.

:>var cursor = db.goods.find();

> printjson(cursor.toArray());  //看到所有行

> printjson(cursor.toArray()[2]);  //看到第2

 

注意: 不要随意使用toArray()

原因: 会把所有的行立即以对象形式组织在内存里.

可以在取出少数几行时,用此功能.


索引创建

1:索引提高查询速度,降低写入速度,权衡常用的查询字段,不必在太多列上建索引

2. 在mongodb,索引可以按字段升序/降序来创建,便于排序

3. 默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引.

 

查看查询计划

db.find(query).explain();

"cursor" : "BasicCursor", ----说明没有索引发挥作用

"nscannedObjects" : 1000 ---理论上要扫描多少行

cursor" : "BtreeCursor sn_1", 用到的btree索引


常用命令:

查看当前索引状态: db.collection.getIndexes();

创建普通的单列索引:db.collection.ensureIndex({field:1/-1});  1是升续2是降续

删除单个索引

db.collection.dropIndex({filed:1/-1});

 

一下删除所有索引

db.collection.dropIndexes();

 

创建多列索引  db.collection.ensureIndex({field1:1/-1, field2:1/-1});

 

创建子文档索引

db.collection.ensureIndex({filed.subfield:1/-1});

 

创建唯一索引:

db.collection.ensureIndex({filed.subfield:1/-1}, {unique:true});

 

创建稀疏索引:

稀疏索引的特点------如果针对field做索引,针对不含field列的文档,将不建立索引.

与之相对,普通索引,会把该文档的field列的值认为NULL,并建索引.

适宜于: 小部分文档含有某列时.

db.collection.ensureIndex({field:1/-1},{sparse:true});

 

> db.tea.find();

{ "_id" : ObjectId("5275f99b87437c610023597b"), "email" : "[email protected]" }

{ "_id" : ObjectId("5275f99e87437c610023597c"), "email" : "[email protected]" }

{ "_id" : ObjectId("5275f9e887437c610023597e"), "email" : "[email protected]" }

{ "_id" : ObjectId("5275fa3887437c6100235980") }

如上内容,最后一行没有email,

如果分别加普通索引,和稀疏索引,

对于最后一行的email分别当成null和 忽略最后一行来处理.

根据{email:null}来查询,前者能查到,而稀疏索引查不到最后一行.

 

创建哈希索引(2.4新增的)

哈希索引速度比普通索引快,但是,无能对范围查询进行优化.

适宜于---随机性强的散列

db.collection.ensureIndex({file:’hashed’});

 

重建索引

一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此.

可以通过索引的重建,减少索引文件碎片,并提高索引的效率.

类似mysql中的optimize table


db.collection.reIndex()

 

Mongodb导出与导入

 

1: 导入/导出可以操作的是本地的mongodb服务器,也可以是远程的.

所以,都有如下通用选项:

-h host   主机

--port port    端口

-u username 用户名

-p passwd   密码


2: mongoexport 导出json格式的文件

: 导出哪个库,哪张表,哪几列,哪几行?

-d  库名  (必填)

-c  表名  (必填)

-f  field1,field2...列名   (不指定表示全部)

-q  查询条件 (不指定表示全部)

-o  导出的文件名 (必填)

-- csv  导出csv格式(便于和传统数据库交换数据)(被遗弃  使用--type csv  CSV模式需要一个字段列表

 

mongoexport -h 192.168.1.32 -d ciika -c promotion -o D:\promotion.json

 

:

[[email protected] mongodb]# ./bin/mongoexport -d test -c news -o test.json

connected to: 127.0.0.1

exported 3 records

[[email protected] mongodb]# ls

bin  dump  GNU-AGPL-3.0  README  test.json  THIRD-PARTY-NOTICES

[[email protected] mongodb]# more test.json

{ "_id" : { "$oid" : "51fc59c9fecc28d8316cfc03" }, "title" : "aaaa" }

{ "_id" : { "$oid" : "51fcaa3c5eed52c903a91837" }, "title" : "today is sataday" }

{ "_id" : { "$oid" : "51fcaa445eed52c903a91838" }, "title" : "ok now" }

 

 

例2: 只导出goods_id,goods_name

./bin/mongoexport -d test -c goods -f goods_id,goods_name -o goods.json

 

3: 只导出价格低于1000元的行

./bin/mongoexport -d test -c goods -f goods_id,goods_name,shop_price -q ‘{shop_price:{$lt:200}}’ -o goods.json

 

: _id列总是导出


Mongoimport 导入

 

-d 待导入的数据库

-c 待导入的表(不存在会自己创建)

--type  csv/json(默认)

--file 备份文件路径

 

1: 导入json

./bin/mongoimport -d test -c goods --file ./goodsall.json

 

2: 导入csv

./bin/mongoimport -d test -c goods --type csv -f goods_id,goods_name --file ./goodsall.csv

 

./bin/mongoimport -d test -c goods --type csv --headline -f goods_id,goods_name --file ./goodsall.csv

 

mongodump 导出二进制bson结构的数据及其索引信息

-d  库名

-c  表名

-f  field1,field2...列名

 

:

mongodum -d test  [-c 表名]  默认是导出到mongo下的dump目录

 

规律:

1:导出的文件放在以database命名的目录下

2: 每个表导出2个文件,分别是bson结构的数据文件, json的索引信息

3: 如果不声明表名,导出所有的表


mongorestore 导入二进制文件

:

 ./bin/mongorestore -d test --directoryperdb dump/test/ (mongodump时的备份目录)

 

二进制备份,不仅可以备份数据,还可以备份索引,

备份数据比较小.

 

MongoDB 备份(mongodump)与恢复(mongorerstore)

 

MongoDB数据备份

在Mongodb中我们使用mongodump命令来备份MongoDB数据。该命令可以导出所有数据到指定目录中。

mongodump命令可以通过参数指定导出的数据量级转存的服务器。

· -h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017

· -d:需要备份的数据库实例,例如:test

· -o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

mongodump -h 192.168.1.32 -d ciika -o D:\Date\mongodb\bak\ciika

MongoDB数据恢复

mongodb使用 mongorerstore 命令来恢复备份的数据。

· -h:MongoDB所在服务器地址

· -d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2

· --drop:恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!

最后加上数据库的目录:

· 例:mongorestore -d ciika --drop D:\Date\mongodb\bak\ciika

 


Mongo VUE 可以和 MongoDB 连接,可是无法打开 collection

解决:MongoDB 3.2之后默认启动的是wiredTiger 引擎这个引擎和原来的引擎访问方式不一样。你用命令mongod  --storageEngine mmapv1 --dbpath 数据目录 这样启动的是原来的数据引擎在用MongoVE连接就可以了


mongodb的用户管理

 

注意:

A)mongodb,有一个admin数据库,牵涉到服务器配置层面的操作,需要先切换到admin数据.

use admin , -->相当于进入超级用户管理模式.

 

B)mongo的用户是以数据库为单位来建立的,每个数据库有自己的管理员.

 

C) 我们在设置用户时,需要先在admin数据库下建立管理员---这个管理员登陆后,相当于超级管理员.


0: 查看用户


1: 添加用户

命令:db.addUser();

简单参数: db.addUser(用户名,密码,是否只读)

 

注意:添加用户后,我们再次退出并登陆,发现依然可以直接读数据库?

原因: mongodb服务器启动时,默认不是需要认证的.

要让用户生效, 需要启动服务器时,就指定--auth选项.

这样, 操作时,就需要认证了.


:

1: 添加用户

> use admin

> db.addUser(‘sa’,’sa’,false);

 

2: 认证

> use test

> db.auth(用户名,密码);

 

3: 修改用户密码

> use test

> db.changeUserPassword(用户名,新密码);

 

3:删除用户

> use test

> db.removeUser(用户名);

 

: 如果需要给用户添加更多的权限,可以用json结构来传递用户参数

 

roles:

read,readWrite,dbAdmin,userAdmin,clusterAdmin

readAnyDatabase,readWriteAnyDatabase

userAdminAnyDatabase,dbAdminAnyDatabase


:

> use test

>db.addUser({user:‘guan‘,pwd:‘111111‘,roles:[‘readWrite,dbAdmin‘]});

 


replication set复制集

replicattion set 多台服务器维护相同的数据副本,提高服务器的可用性.

 

Replication set 设置全过程

0:创建目录

mkdir -p /data/r0 /data/r1 /data/r2


1:启动3个实例,声明实例属于某复制集

./bin/mongod --port 27017 --dbpath /data/r0 --smallfiles --replSet rsa --fork --logpath /var/log/mongo17.log

./bin/mongod --port 27018 --dbpath /data/r1 --smallfiles --replSet rsa --fork --logpath /var/log/mongo18.log

./bin/mongod --port 27019 --dbpath /data/r2 --smallfiles --replSet rsa --fork --logpath /var/log/mongo19.log

 

2:配置

rsconf = {

    _id:‘rsa‘,

    members:

    [

        {_id:0,

        host:‘192.168.1.201:27017‘

        }

    ]

}


3: 根据配置做初始化

rs.initiate(rsconf);

 

4: 添加节点

rs.add(‘192.168.1.201:27018‘);

rs.add(

以上是关于mongodb学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 学习笔记一: 配置

MongoDB快速入门学习笔记1 windows安装MongoDB

MongoDB学习笔记 MongoDB介绍及安装

MongoDB 学习笔记二:安装MongoDB

MongoDB系列之学习笔记教程汇总

MongoDB系列之学习笔记教程汇总