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/