您的位置:首页 > 数据库 > Mongodb

mongodb操作(概述以及相关的命令)

2015-12-15 21:31 549 查看
http://blog.csdn.net/ljfbest/article/details/11979609

Mongodb的体系结构

关系型数据库Mysql:数据库(database)、表(table)、记录(rows)三个层次组成

非关系型数据库Mongodb:数据库(database)、集合(collection)、文档对象(document)三个层次组成

MongoDB里的集合对应于关系型数据库里的表,但是集合中没有列、行和关系的概念,集合中只有文档,一个文档就相当于一条记录,这体现了模式自由的特点。

数据存储结构

mysql的数据存储结构:每个数据库存放在一个与数据库同名的文件夹中,如果使用MyISAM存储引擎,数据库文件类型就包括.frm、.MYD、.MYI。

mongodb的数据存储结构:默认数据目录是/data/db,它负责存储所有的MongoDB的数据文件。在MongoDB内部,每个数据库都包含一个.ns文件和一些数据文件,而且这些数据文件会随着数据量的增加而变得越来越多。

所以如果系统中有一个叫做mydb的数据库,那么构成mydb这个数据库的文件就会由mydb.ns,mydb.0,mydb.1组成

-rwxr-xr-x 1 root root   6 05-09 12:59 mongod.lock

-rw——- 1 root root 16M 05-09 07:03 test.0

-rw——- 1 root root 32M 05-09 07:03 test.1

-rw——- 1 root root 16M 05-09 07:03 test.ns

 

show dbs查看数据库

db当前数据库

show tables/show collections显示集合

db.dropDatabase()删除当前数据库

db.集合名.drop(),删除集合

use 数据库名,定义新的数据库名

db.数据库名.remove(),清空集合

想知道更多命令,可以直接输入help

mongodb操作

插入 insert/save

Insert 如果主键相同则插入不成功,save则是更新这个文档

//定义文档

>doc = {

“_id” : 1,

“author” : “sam”,

“title” : “i love you”,

“text” : “this is a test”,

“tags” : [

"love",

"test"

],

“comments” : [

{

"author" : "jim",

"comment" : "yes"

},

{

"author" : "tom",

"comment" : "no"

}

]

}

//插入文档

> db.c1.insert(doc);

 

删除:db.c1.remove();c1中的文档全部删除

Db.c1.remove({name:”user1”});删除name是user1的

 

查询

db.c1.find()查询c1下所有

db.users.find({name: ‘user1′})

 

只返回某些特定的字段值:

//返回除了age字段外的所有字段

> db.user.find({},{age:0});

//返回tags=tennis 除了comments的所有列

db.posts.find( { tags : ‘tennis’ }, { comments : 0 } );

//返回userid=16的name字段

> db.user.find({userid:16},{name:1});

{ “_id” : 16, “name” : “user16″ }

//返回x=john的所有z字段

db.things.find( { x : “john” }, { z : 1 } );

注:  _id字段始终都会被返回,哪怕没有明确指定,如果不想返回要明确指定{_id:0}

 

1)  <, <=, >, >=

语法: (注意魔术方法条件在内侧)

// 大于: field > value

db.collection.find({ “field” : { $gt: value } } );

//小于:field < value

db.collection.find({ “field” : { $lt: value } } );

//大于等于: field >= value

db.collection.find({ “field” : { $gte: value } } );

//小于等于:field<=value

db.collection.find({ “field” : { $lte: value } } );

//区间查询

> db.user.find({_id:{$gt:5,$lte:10}});

//不等于

db.c1.find({_id:{$ne:5}});

 

排序,按照last_name 属性进行升序排序返回所有文档:

//1表示升序,-1表示降序

db.users.find({}).sort({last_name: 1});

 

count()

count()方法返回查询记录的总数目

> db.user.find().count();

> db.user.find({_id:{$lt:20}}).count();

 

limit()

> db.user.find().limit(5);

注意,下面和mysql不一样

> db.c1.find().limit(2,5); //只取出2条,要相达到mysql结果需要结合skip();

> db.c1.find().skip(2).limit(5);

 

//先执行排序再limit,count没有参数只会返回db.c1.find()的查询的条数

> db.c1.find().sort({age:-1}).skip(2).limit(5).count();

> db.c1.find().sort({age:-1}).skip(2).limit(5).count(1); //5

 

$all 操作要求数组里面的值全部被包含在返回的记录里面,如:

> use test;

switched to db test

> db.things.insert({a:[1,2,3]});

> db.things.find();

{ “_id” : ObjectId(“4de73360059e7f4bdf907cfe”), “a” : [ 1, 2, 3 ] }

> db.things.find({a:{$all:[2,3]}});

{ “_id” : ObjectId(“4de73360059e7f4bdf907cfe”), “a” : [ 1, 2, 3 ] }

> db.things.find({a:{$all:[1,2,3]}});

{ “_id” : ObjectId(“4de73360059e7f4bdf907cfe”), “a” : [ 1, 2, 3 ] }

> db.things.find({a:{$all:[1]}});

{ “_id” : ObjectId(“4de73360059e7f4bdf907cfe”), “a” : [ 1, 2, 3 ] }

> db.things.find({a:{$all:[1,2,3,4]}});

 

$exists操作检查一个字段是否存在,

//包含_id,索引

> db.user.find({_id:{$exists:1}})

 

$mod操作可以进行取模操作,而不需要用到where子句,如

//where子句

> db.user.find(“this._id%10==1″).limit(5);

//$mod操作

> db.user.find({_id:{$mod:[10,1]}}).limit(5);

 

$in操作类似于传统关系数据库中的IN

//数据库中有所有数组对应的记录

> db.user.find({_id:{$in:[2,3,4,5,6]}}).limit(5);

{ “_id” : 2, “name” : “user2″, “userid” : 2, “age” : 20 }

{ “_id” : 6, “name” : “user6″, “userid” : 6, “age” : 20 }

$nin跟$in操作相反,看例子:

//扣掉_id=1/2/3/4的记录

> db.user.find({_id:{$nin:[1,2,3,4]}}).limit(5);

{ “_id” : 0, “name” : “user0″, “userid” : 0, “age” : 20 }

{ “_id” : 5, “name” : “user5″, “userid” : 5, “age” : 20 }

 

$or 和$nor例外,魔术方法在外侧

> db.user.find({$or:[{_id:2},{name:'user3'},{userid:4}]}).limit(5);

{ “_id” : 2, “name” : “user2″, “userid” : 2, “age” : 20 }

{ “_id” : 3, “name” : “user3″, “userid” : 3, “age” : 20 }

{ “_id” : 4, “name” : “user4″, “userid” : 4, “age” : 20 }

$nor跟$or相反,不好解释,看例子:

> db.user.find({$nor:[{_id:2},{name:'user3'},{userid:4}]}).limit(5);

{ “_id” : 0, “name” : “user0″, “userid” : 0, “age” : 20 }

{ “_id” : 1, “name” : “user1″, “userid” : 1, “age” : 20 }

{ “_id” : 5, “name” : “user5″, “userid” : 5, “age” : 20 }

可以看到,_id=2,name=user3和userid=4的记录都被过滤了

 

$size操作将会查询数组长度等于输入参数的数组,例子:

> db.things.find({a:{$size:3}});

{ “_id” : ObjectId(“4de73360059e7f4bdf907cfe”), “a” : [ 1, 2, 3 ] }

 

正则表达式:遵循常规正则的语法

//检索name属性是以u开头,4结尾的所有用户

> db.user.find({name:/u.*4$/i}).limit(5);

 

Distinct

类似于关系数据库中的Distinct,如:

> db.addresses.insert({“zip-code”: 10010})

> db.addresses.insert({“zip-code”: 10010})

> db.addresses.insert({“zip-code”: 99701})

> // shell helper:

> db.addresses.distinct(“zip-code”);

[ 10010, 99701 ]

> // running as a command manually:

> db.runCommand( { distinct: ‘addresses’, key: ‘zip-code’ } )

{ “values” : [ 10010, 99701 ], “ok”

//

> db.comments.save({“user”: {“points”: 25}})

> db.comments.save({“user”: {“points”: 31}})

> db.comments.save({“user”: {“points”: 25}})

> db.comments.distinct(“user.points”);

[ 25, 31 ]

 

$elemMatch 主要是为了避免一些服务器语言语法的障碍

> t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } )

{ “_id” : ObjectId(“4b5783300334000000000aa9″),

“x” : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]

}

//同样效果

> t.find( { “x.a” : 1, “x.b” : { $gt : 1 } } )

 

$slice

db.posts.find({}, {comments:{$slice: 5}}) // 前5条评论

db.posts.find({}, {comments:{$slice: -5}}) //后5条评论

db.posts.find({}, {comments:{$slice: [20, 10]}}) // skip 20, limit 10

db.posts.find({}, {comments:{$slice: [-20, 10]}}) // 20 from end, limit 10

 

NULL查询

//包含NULL情况的查询

> db.foo.insert( { x : 1, y : 1 } )

> db.foo.insert( { x : 2, y : “string” } )

> db.foo.insert( { x : 3, y : null } )

> db.foo.insert( { x : 4 } )

 

// Query #1

> db.foo.find( { “y” : null } )

{ “_id” : ObjectId(“4dc1975312c677fc83b5629f”), “x” : 3, “y” : null }

{ “_id” : ObjectId(“4dc1975a12c677fc83b562a0″), “x” : 4 }

// Query #2

> db.foo.find( { “y” : { $type : 10 } } )

{ “_id” : ObjectId(“4dc1975312c677fc83b5629f”), “x” : 3, “y” : null }

// Query #3

> db.foo.find( { “y” : { $exists : false } } )

{ “_id” : ObjectId(“4dc1975a12c677fc83b562a0″), “x” : 4 }

 

$type将会根据字段的BSON类型来检索数据,例如:

//返回a是字符串的记录

db.things.find( { a : { $type : 2 } } ); // matches if a is a string

//返回a是int类型的记录

db.things.find( { a : { $type : 16 } } ); // matches if a is

an int

下是BSON主要数据类型映射:

 

Double  1

String  2

Object  3

Array  4

Binary data  5

Object id  7

Boolean  8

Date  9

Null  10

Regular expression  11

JavaScript code  13

Symbol  14

JavaScript code with scope 15

32-bit integer  16

Timestamp  17

64-bit integer  18

Min key  255

Max key  127

 

 

更改操作:

db.collection.update( criteria, objNew, upsert, multi )

参数说明:

Criteria:用于设置查询条件的对象

Objnew:用于设置更新内容的对象

Upsert:如果记录已经存在,更新它,否则新增一个记录 一般设置为0

Multi:如果有多个符合条件的记录,全部更新 一般设置为1

注意:默认情况下,只会更新第一个符合条件的记录

 

> for(i=1;i<10;i++){ db.c1.insert({name:”user”+i,age:i}); }

> db.c1.find();

{ “_id” : ObjectId(“518c452a644bcedf5c9be88c”), “name” : “user1″, “age” : 1 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be88d”), “name” : “user2″, “age” : 2 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be88e”), “name” : “user3″, “age” : 3 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be88f”), “name” : “user4″, “age” : 4 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be890″), “name” : “user5″, “age” : 5 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be891″), “name” : “user6″, “age” : 6 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be892″), “name” : “user7″, “age” : 7 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be893″), “name” : “user8″, “age” : 8 }

{ “_id” : ObjectId(“518c452a644bcedf5c9be894″), “name” : “user9″, “age” : 9 }

 

> db.c1.update({name:”user5″},{sex:”m”});

更改后name为user5的那条文档变为下面这样:

{ “_id” : ObjectId(“518c452a644bcedf5c9be890″), “sex” : “m” }

> db.c1.update({name:”user1″},{name:”ljf”});//原来的记录会变为下面的

{ “_id” : ObjectId(“518c452a644bcedf5c9be88c”), “name” : “ljf” }//age没有了

> db.c1.update({name:”kitty”},{name:”ljf”}); //没有name为kitty的记录,所以不成功

> db.c1.update({name:”kitty”},{name:”ljf”},1);//会增加这一条记录

如果想要达到类似mysql的update效果,应该用$set

{ $set : { field : value } }

功能: 把field的值设置成value,当field不存在时,增加一个字段,类似SQL的set操

作,value支持所有类型

> db.c1.update({name:”user2″},{$set:{name:”ljf”,age:22,sex:”f”}},0,1); //则这条记录变为以下

{ “_id” : ObjectId(“518c452a644bcedf5c9be88d”), “age” : 22, “name” : “ljf”, “sex” : “f” }

 

$inc

{ $inc : { field : value } }

功能: 把field的值加一个value,如果没有这个field则会自动创建

例子:我要对一个_id=0的user的年龄进行加1,普通的做法如下:

> var u = db.user.findOne({_id:0});

> u

{ “_id” : 0, “name” : “user0″, “userid” : 0, “age” : 21 }

> u.age++

21

> db.user.save(u);

> var u = db.user.findOne({_id:0});

> u

{ “_id” : 0, “name” : “user0″, “userid” : 0, “age” : 22 }

>

但是有了$inc操作符呢,就不需要这么麻烦:

> db.user.update({_id:0},{$inc:{age:1}});

> var u = db.user.findOne({_id:0});

> u

{ “_id” : 0, “name” : “user0″, “userid” : 0, “age” : 23 }

 

$set与$inc自动创建字段却不能删除,这时可以用$unset

{ $unset : { field : 1} }

功能: 删除给定的字段field

//删除上一步增加的sex字段

> db.user.findOne({_id:0});

{ “_id” : 0, “age” : 20, “name” : “user0″, “sex” : “boy”, “userid” : 0 }

> db.user.update({_id:0},{$unset:{sex:1}});

> db.user.findOne({_id:0});

{ “_id” : 0, “age” : 20, “name” : “user0″, “userid” : 0 }

 

$push

语法: { $push : { field : value } }

功能: 如果filed是一个已经存在的数组,那么把value追加给field;如果field原来不存在,那么新增field字段,把value的值赋给field;如果field存在,但是不是一个数组,将会出错;

 

$pushAll

语法: { $pushAll : { field : value_array } }

功能: 功能同$push,只是这里的value是数组,相当于对数组里的每一个值进行$push操作


mongodb 数据库管理

索引:索引信息存储在system.indexes中,mongodb中_id字段在创建时候,默认已经建立了索引,这个索引不能被删除。

建立普通索引:db.c1.ensureIndex({name:1});

当系统已有大量数据时,创建索引非常耗时,要在后台执行,只需执行加上”background:true”执行即可。

db.c1.getIndexKeys();//查看c1索引的字段

db.c1.getIndexes();//查看c1索引的详细信息

db.c1.find({name:”user5″}).explain();//查看此查询语句索引使用情况

添加唯一索引:db.c1.ensureIndex({age:1},{unique:1});

删除索引:

db.c1.dropIndex({age:1});

db.c1.dropIndexes();//不会删除_id索引

慢查询

MongoDB Database Profiler是一种慢查询日志功能,可以作为我们优化数据库的依据。profile的级别可以取0,1,2三个值,它们表示:

0- 不开启

1- 记录慢命令(默认为>100ms)

2- 记录所有命令

db.getProfilingLevel();//查看是否开启了慢查询

db.setProfilingLevel(1);

启动时可以修改默认慢查询参数100ms:db.setProfilingLevel(1,100);

性能监控

Mongosniff

此工具可从底层监控到底有哪些命令发送给MongoDB去执行。

[root@localhost bin]# ./mongosniff –source net lo

[root@localhost bin]# ./mongostat

数据导出/导入:mongoexport、mongoimport

mongoexport -d test -c collection -o 导出的文件名

参数说明:

-d 数据库名称

-c 集合名称

-o 导出的文件名称

./mongoimport -d test -c c1 /tmp.c1.out

数据备份 数据恢复mongodump、mongorestore

mongodump -d test

此时会在当前目录下默认创建一个dump目录,用于存放备份出来的文件也可以。单个集合的备份是可以成功,但单个集合的恢复不成功

mongodump -d test -c c5 -o mydump/c5

这样写才对

mongorestore -d test mydump/c5/test OK

用户授权

每个MongoDB实例中的数据库都有许多用户,如果启用了安全性认证后,只有数据认证的用户才可以进行读写操作

MongoDB默认的启动是不验证用户名和密码的,启动MongoDB后,可以直接用mongo连接上来,对所有的库具有root权限,所以启动的时候指定参数,可以阻止客户端的访问和连接,只需要在启指定–auth参数即可

mongod –auth

添加数据库管理员

use admin;

db.addUser(“root”:”123″);

管理员分为系统管理员和数据库管理员

系统管理员必须添加到admin数组库中,

use admin;

db.addUser(“root”,”123456″);

然后用

mongo -uroot -p123456 localhost:27017/admin

然后为其它数据库设置管理员

use test

db.addUser(“user1″,”123456″);

现在就能用user1来管理test数据库了

可以通过db.system.users.find();来查看数据库中的所用管理员信息

mongo -uuser1 -p123456 localhost:27017/test

为什么还可以登陆呢?在最初始的时候MongoDB都默认有一个admin数据库(默认是空的)admin.system.users中将会保存具有管理员权限的用户

注意: 当admin.system.users中没有添加任何用户时,即使MongoDB启动时添加–auth参数,如果有除admin数据库中添加了用户,此时不进行任何认证依然可以使用任操作,直到你在admin.system.users中添加了一个用户

建立一个系统root用户

在admin库中新添一个用户root

use admin

db.addUser(‘root’,’123′);

db.auth(“root”,’123′);

建立指定权限用户

mongoDB也支持为某个特定的数据库来设置用户

如我们为test库设一个只读的用户user_reader

db.addUser(“user1″,”pass1″,true);

只要在db.addUser函数的第三个参数国中true即可为只读,只有在test库,有只读的权限
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: