MongoDB入门教程(包含安装、常用命令、相关概念、使用技巧、常见操作等)
一、安装和配置
MongoDB的官方下载站是http://www.mongodb.org/downloads,可以去上面下载最新的安装程序
Windows平台的安装
●步骤一:下载MongoDB
点击上方官方下载地址,并下载Windows版本
●步骤二:设置MongoDB程序存放目录
下载完成后,解压到自定义文件夹,例:D:\mongodb\
●步骤三:设置数据文件存放目录
在D:\mongodb\目录下创建db和logs文件夹(和bin目录同级),
随后在logs文件夹内创建mongodb.log日志文件
●步骤四:启动MongoDB服务,作为Windows服务
//进入cmd控制台 D:/mongodb/bin>mongod.exe--logpathD:/mongodb/logs/mongodb.log--logappend --dbpathD:/mongodb/db --directoryperdb --serviceNameMongoDB --install --directoryperdb指定每个DB都会新建一个目录
安装完成后,就可以在cmd下用命令netstartMongoDB和netstopMongoDB来启动和停止MongoDB了
●步骤五:客户端连接验证
打开cmd输入:D:/mongodb/bin>mongo.exe
D:/mongodb/bin>mongo.exe MongoDBshellversion:2.4.8 connectingto:test >
Linux平台的安装
●步骤一:下载MongoDB
点击上方官方下载地址,并下载Linux版本
●步骤二:设置MongoDB程序存放目录
下载完成后,解压到自定义文件夹,例:/usr/local/mongo
●步骤三:设置数据文件存放目录
创建/data/db和/data/logs文件夹,随后在logs文件夹内创建mongodb.log日志文件
●步骤四:启动MongoDB服务,作为Linux服务随机启动
vi/etc/rc.local//使用vi编辑器打开配置文件,并在其中加入下面一行代码 /usr/local/mongo/bin/mongod--dbpath=/data/db/--logpath=/data/logs/mongodb.log--logappend&
安装完成后,可以使用pkillmongod来结束
二、数据逻辑结构
●MongoDB的文档(document),相当于关系数据库中的一行记录。
●多个文档组成一个集合(collection),相当于关系数据库的表。
●多个集合(collection),逻辑上组织在一起,就是数据库(database)。
●一个MongoDB实例支持多个数据库(database)。
●默认端口:27017
三、常用命令
选择数据库
usepersons
显示当前数据库
db || db.getName()
删除当前数据库
db.dropDatabase()
显示当前数据库下的集合Collections
showtables||showcollections
显示当前system.profile
showprofile
显示当前数据库下的用户Users
showusers
添加用户
db.addUser(username,password)
删除用户
db.removeUser(username)
四、索引ensureIndex()
//普通索引 db.persons.ensureIndex({name:1}); db.factories.insert({name:"xyz",metro:{city:"NewYork",state:"NY"}}); //文档式索引 db.factories.ensureIndex({metro:1}); //嵌入式索引 db.factories.ensureIndex({"metro.city":1}); //组合索引 db.things.ensureIndex({name:-1,qty:1}); //唯一索引 db.user.ensureIndex({firstname:1,lastname:1},{unique:true}); /*当一个记录被插入到唯一性索引文档时,缺失的字段会以null为默认值被插入文档*/ db.things.save({lastname:"Smith"}); //下面这个操作将会失败,因为firstname上有唯一性索引,值为null db.things.save({lastname:"Jones"}); //查看索引 db.persons.getIndexes(); //删除所有索引 db.collection.dropIndexes(); //删除单个索引 db.collection.dropIndex({x:1,y:-1});
五、增删改查等
//定义文档 >doc={ "_id" :1, "author" :"sam", "title" :"iloveyou", "text" :"thisisatest", "tags" :["love","test"], "comments":[ {"author":"jim","comment":"yes"}, {"author":"tom","comment":"no"} ] } //插入文档 >db.posts.insert(doc); //查找文档 >db.posts.find({'comments.author':'jim'});
查询Query
//查询集合中的所有记录: db.users.find({}) //查询出所有“last_name”属性值为“Smith”的文档记录 db.users.find({'last_name':'Smith'})
查询选项
//返回除了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字段始终都会被返回,哪怕没有明确指定
条件表达式
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}}); //区间查询 5<field<=10 >db.collection.find({"field":{$gt:5,$lte:10}});
$all操作类似$in操作,但是不同的是,$all操作要求数组里面的值全部被包含在返回的记录里面
>usetest; switchedtodbtest >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操作检查一个字段是否存在
//userid字段存在 >db.user.find({userid:{$exists:true}}).limit(1); {"_id":1,"name":"user1","userid":1,"age":20} //sex字段不存在 >db.user.find({sex:{$exists:true}}).limit(1); > >
$mod操作可以让我们简单的进行取模操作
//where子句 >db.user.find("this._id%10==1").limit(5); //$mod操作 >db.user.find({_id:{$mod:[10,1]}}).limit(5);
$ne意思是不等于(notequal)
>db.user.find().limit(2); {"_id":0,"name":"user0","userid":0,"age":20} {"_id":1,"name":"user1","userid":1,"age":20} >db.user.find({_id:{$ne:0}}).limit(2); {"_id":1,"name":"user1","userid":1,"age":20}
$in操作类似于传统关系数据库中的IN
//数据库中有所有数组对应的记录 >db.user.find({_id:{$in:[2,3]}}).limit(5); {"_id":2,"name":"user2","userid":2,"age":20} {"_id":3,"name":"user3","userid":3,"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} {"_id":6,"name":"user6","userid":6,"age":20}
$or
>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(4); {"_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":6,"name":"user6","userid":6,"age":20} >
$size操作将会查询数组长度等于输入参数的数组
>db.things.find(); {"_id":ObjectId("4de73360059e7f4bdf907cfe"),"a":[1,2,3]} >db.things.find({a:{$size:3}}); {"_id":ObjectId("4de73360059e7f4bdf907cfe"),"a":[1,2,3]} >db.things.find({a:{$size:2}}); > >db.things.find({a:{$size:1}}); >
$where
>db.mycollection.find({$where:function(){returnthis.a==3||this.b==4;}}); //同上效果 >db.mycollection.find(function(){returnthis.a==3||this.b==4;});
$type将会根据字段的BSON类型来检索数据
//返回a是字符串的记录 >db.things.find({a:{$type:2}}); //返回a是int类型的记录 >db.things.find({a:{$type:16}});
类型名称映射
●Double:1
●String:2
●Object:3
●Array:4
●Binarydata:5
●Objectid:7
●Boolean:8
●Date:9
●Null:10
●Regularexpression:11
●JavaScriptcode:13
●Symbol:14
●JavaScriptcodewithscope:15
●32-bitinteger:16
●Timestamp:17
●64-bitinteger:18
●Minkey:255
●Maxkey:127
Mongodb同样支持正则表达式进行检索
//检索name属性是以u开头,4结尾的所有用户 >db.user.find({name:/u.*4$/i}).limit(2); {"_id":4,"name":"user4","userid":4,"age":20} {"_id":14,"name":"user14","userid":14,"age":20} //同样效果的查询语句 >db.user.find({name:{$regex:'u.*4$',$options:'i'}}).limit(2); {"_id":4,"name":"user4","userid":4,"age":20} {"_id":14,"name":"user14","userid":14,"age":20} //配合其他操作一起使用 >db.user.find({name:{$regex:'u.*4$',$options:'i',$nin:['user4']}}).limit(2); {"_id":14,"name":"user14","userid":14,"age":20}
排序
按照last_name属性进行升序排序返回所有文档
//1表示升序,-1表示降序 db.users.find({}).sort({last_name:1});
Group
//语法: db.coll.group({ cond :{filed:conditions}, key :{filed:true}, initial :{count:0,total_time:0}, reduce :function(doc,out){}, finalize:function(out){} }); 参数说明: Key :对那个字段进行 GroupCond :查询条件 Initial :初始化group计数器 Reduce :通常做统计操作 Finalize :通常都统计结果进行进一步操作,例如求平均值Keyf:用一个函数来返回一个替代KEY的值 //例子 >db.test.group({ cond :{"invoked_at.d":{$gte:"2009-11",$lt:"2009-12"}}, key :{http_action:true}, initial :{count:0,total_time:0}, reduce :function(doc,out){out.count++;out.total_time+=doc.response_time}, finalize:function(out){out.avg_time=out.total_time/out.count}}); [ { "http_action":"GET/display/DOCS/Aggregation", "count" :1, "total_time" :0.05, "avg_time" :0.05 } ]
去重类似于关系数据库中的Distinct
>db.addresses.insert({"zip-code":10010}) >db.addresses.insert({"zip-code":10010}) >db.addresses.insert({"zip-code":99701}) > >db.addresses.distinct("zip-code"); [10010,99701] > >//command模式: >db.runCommand({distinct:'addresses',key:'zip-code'}) {"values":[10010,99701]} > >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]
Mongodb支持skip和limit命令来进行分页查询
//跳过前10条记录 >db.user.find().skip(10); //每页返回8条记录 >db.user.find().limit(8); //跳过前20条记录,并且每页返回10条记录 >db.user.find().skip(20).limit(8); //下面这个语句跟上一条一样,只是表达不够清晰 >db.user.find({},{},8,20);
$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}})
count()方法返回查询记录的总数
db.orders.count({ord_dt:{$gt:newDate('01/01/2012')}}) //同样效果 db.orders.find({ord_dt:{$gt:newDate('01/01/2012')}}).count() //当查询语句用到了skip()和limit()方法的时候, //默认情况下count()会忽略这些方法,如果想要计算这些方法, //需要给count()方法传一个true作为参数 >db.user.find({_id:{$lt:20}}).skip(3).limit(9).count(); 20 >db.user.find({_id:{$lt:20}}).skip(3).limit(9).count(true); 9 >
$slice
db.posts.find({},{comments:{$slice:5}})//前5条评论 db.posts.find({},{comments:{$slice:-5}})//后5条评论 db.posts.find({},{comments:{$slice:[20,10]}})//跳过20条,limit10 db.posts.find({},{comments:{$slice:[-20,10]}})//后20条,limit10
删除Delete
Remove操作用于从集合中删除记录
//删除一条记录 >db.stu.remove({_id:17}); //删除所有记录 >db.stu.remove({}); //某些情况下,当你在对一个记录执行remove操作的时候, //可能会有update操作在这个记录上,这样就可能删除不掉这个记录, //如果你觉得这不尽人意,那么你可以在remove操作的时候加上$atomic: db.stu.remove({rating:{$lt:3.0},$atomic:true});
更新Update
db.collection.update(criteria,objNew,upsert,multi)
参数说明:
Criteria:用于设置查询条件的对象
Objnew :用于设置更新内容的对象
Upsert :如果记录已经存在,更新它,否则新增一个记录
Multi :如果有多个符合条件的记录,全部更新注意:默认情况下,只会更新第一个符合条件的记录
save()
//如果存在更新它,如果不存在,新增记录 db.mycollection.save({name:'shawn'});
$inc
{$inc:{field:value}}//把field的值加一个value >db.user.findOne({_id:0}); {"_id":0,"name":"user0","userid":0,"age":22} >db.user.update({_id:0},{$inc:{age:1}}); {"_id":0,"name":"user0","userid":0,"age":23}
$set
{$set:{field:value}} //把field的值设置成value,当field不存在时,增加一个字段, //类似SQL的set操作,value支持所有类型 //把上面的age改回到20 >db.user.update({_id:0},{$set:{age:20}}); {"_id":0,"name":"user0","userid":0,"age":20} //当field不存在时,增加一个字段 >db.user.update({_id:0},{$set:{sex:'boy'}}); {"_id":0,"sex":"boy","name":"user0","userid":0,"age":20}
$unset
{$unset:{field:1}}//删除给定的字段field //删除上一步增加的sex字段 >db.user.update({_id:0},{$unset:{sex:1}}); {"_id":0,"name":"user0","userid":0,"age":20}
$push
{$push:{field:value}} //如果filed是一个已经存在的数组,那么把value追加给field //如果field原来不存在,那么新增field字段,把value的值赋给field //如果field存在,但是不是一个数组,将会出错 >db.sport.update({_id:0},{$push:{aihao:'football'}});
$pushAll
{$pushAll:{field:value_array}} //功能同$push,只是这里的value是数组,相当于对数组里的每一个值进行$push操作
$addToSet
{$addToSet:{field:value}} //如果filed是一个已经存在的数组,并且value不在其中,那么把value加入到数组 //如果filed不存在,那么把value当成一个数组形式赋给field //如果field是一个已经存在的非数组类型,那么将会报错
$pop
{$pop:{field:1}} //删除数组中最后一个元素 {$pop:{field:-1}} //删除数组中第一个元素
$pull
{$pull:{field:_value}} //如果field是一个数组,那么删除符合_value检索条件的记录 //如果field是一个已经存在的非数组,那么会报错
$pullAll
{$pullAll:{field:value_array}}//同$push类似,只是value的数据类型是一个数组
$rename
{$rename:{old_field_name:new_field_name} //重命名指定的字段名称,从1.7.2版本后开始支持 >db.user.update({_id:0},{$rename:{'quantity':'qty'}});
特殊操作符:$
$操作符代表查询记录中第一个匹配条件的记录项
//例1 >db.t.find() { "_id" :ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" :"ABC", "comments":[ {"by":"joe","votes":3}, {"by":"jane","votes":7} ] } >db.t.update({'comments.by':'joe'},{$inc:{'comments.$.votes':1}},false,true) >db.t.find() { "_id" :ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" :"ABC", "comments":[ {"by":"joe","votes":4}, {"by":"jane","votes":7} ] } //例2 >db.t.find(); { "_id":ObjectId("4b9e4a1fc583fa1c76198319"), "x" :[1,2,3,2] } >db.t.update({x:2},{$inc:{"x.$":1}},false,true); >db.t.find(); { "_id":ObjectId("4b9e4a1fc583fa1c76198319"), "x" :[1,3,3,2] } //在数组中用$配合$unset操作符的时候,效果不是删除匹配的元素,而是把匹配的元素变成了null,如: >db.t.insert({x:[1,2,3,4,3,2,3,4]}) >db.t.find() { "_id":ObjectId("4bde2ad3755d00000000710e"), "x" :[1,2,3,4,3,2,3,4] } >db.t.update({x:3},{$unset:{"x.$":1}}) >t.find() { "_id":ObjectId("4bde2ad3755d00000000710e"), "x" :[1,2,null,4,3,2,3,4] }
图形化管理工具
MongoDB有几款图形化的管理工具,参考:
http://docs.mongodb.org/ecosystem/tools/administration-interfaces/