1.mongodb启动
./mongod --dbpath=/usr/local/mongo/data/db/ --logpath=/usr/local/mongo/data/logs --fork --port 27017
解释:
--dbpath:数据库路径
--logpath:日志路径
--fork:后台运行
--port:端口(默认端口:27017)
2.正常关闭mongodb
./mongod -shutdown --dbpath=/usr/local/mongo/data/db
3.mongodb命令
1)show dbs;查看当前数据库
2)use test;切换数据库
3)show tables/collections;查看当前库下的表
4)新增操作
a)db.user.insert({name:'dengchao',age:29,gender:'m'});新增数据库及数据填充(user为新增数据库,隐式新增)
b)db.user.insert([{name:'panjinlian',age:35},{name:'wudalang',age:50,add:'changanjie'}]);一次性增加多条数据
5)删除操作
a)db.user.remove();删除user库中的所有数据,
b)db.user.remove({name:'dengchao'});根据条件删除user表中的数据
6)修改操作
a)$set:修改某一字列的值
b)$unset:删除某一列
c)$rename:修改某一列的名称
d)$inc:增加某一列的值
e)$setOnInsert:当upsert为true时,并且发生了insert操作时,可以补充的字段
列1:db.user.update({name:'wukong'},{$set:{name:'qtds'},$unset:{jingu:true},$inc:{age:18},$rename:{sex:'gender'}});
列2:db.user.update({name:'aaa'},{$set:{age:90},$setOnInsert:{gender:'male'}},{$upsert:true})
7)可选项操作
a)$upsert:true/false(是指没有匹配的行,则直接插入该行.(和mysql中的replace一样))
例:db.stu.update({name:'wuyong'},{$set:{name:'junshiwuyong'}},{upsert:true});
如果有name=’wuyong’的文档,将被修改
如果没有,将添加此新文档
b)multi:true/false(是指修改多行(即使查询表达式命中多行,默认也只改1行,如果想改多行,可以用此选项)
例:db.news.update({age:21},{$set:{age:22}},{multi:true});
则把news中所有age=21的文档,都修改
8)查询操作
a)db.user.find():查询所有的数据
b)db.user.find({},{name:1}):查询所有记录中的name字段,_id字段默认是显示的
c)db.user.find({},{name:1,_id:0}):查询所有记录中的name字段,不显示_id
d)db.stu.find({gender:’male’},{name:1,_id:0});查询所有gender属性值为male的文档中的name属性
9)查询表达式练习
查出满足以下条件的商品
1.1:主键为32的商品
db.goods.find({goods_id:32});
1.2:不属第3栏目的所有商品($ne)
db.goods.find({cat_id:{$ne:3}},{goods_id:1,cat_id:1,goods_name:1,_id:0});
1.3:本店价格高于3000元的商品{$gt}
db.goods.find({shop_price:{$gt:3000}},{goods_id:1,goods_name:1,_id:0});
1.4:本店价格低于或等于100元的商品($lte)
db.goods.find({shop_price:{$lte:100}},{goods_id:1,goods_name:1,_id:0,shop_price:1});
1.5:取出第4栏目或第11栏目的商品($in)
db.goods.find({cat_id:{$in:[4,11]}},{goods_id:1,goods_name:1,_id:0,cat_id:1});
1.6:取出100<=价格<=500的商品($and)
db.goods.find({$and:[{shop_price:{$gte:100}},{shop_price:{$lte:500}}]},{goods_name:1,_id:0,shop_price:1});
1.7:取出不属于第3栏目且不属于第11栏目的商品($and $nin和$nor分别实现)
db.goods.find({$and:[{cat_id:{$ne:3}},{cat_id:{$ne:11}}]},{goods_name:1,_id:0,cat_id:1});
db.goods.find({cat_id:{$nin:[3,11]}},{goods_name:1,_id:0,cat_id:1});
db.goods.find({cat_id:{$nin:[3,11]}},{goods_name:1,_id:0,cat_id:1});
1.8:取出价格大于100且小于300,或者大于4000且小于5000的商品
db.goods.find({$or:[{$and:[{shop_price:{$gt:100}},{shop_price:{$lt:300}}]},{$and:[{shop_price:{$gt:4000}},{shop_price:{$lt:5000}}]}]},{goods_name:1,shop_price:1,_id:0});
1.9:取出以诺基亚开头的商品$regex
db.goods.find({$regex:{goods_name:/^诺基亚.*/}});
10)游标操作(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()
原因: 会把所有的行立即以对象形式组织在内存里.
可以在取出少数几行时,用此功能.
11)索引
1:索引提高查询速度,降低写入速度,权衡常用的查询字段,不必在太多列上建索引
2. 在mongodb中,索引可以按字段升序/降序来创建,便于排序
3. 默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引.
a)查看索引计划
db.bar.find().explain();
b)查看索引
db.bar.getIndexes();
c)创建索引
1)单列索引
db.bar.ensureIndex({title:1});解释:1:正序;-1:反序
2)多列索引
db.bar.ensureIndex({title:1,content:1});
3)子文档添加索引
db.shop.insert({name:'NOKIA',spc:{title:'shouji',are:'hanguo'}});//子文档数据
db.shop.ensureIndex({'spc.are':1});//子文档下的属性添加索引
db.shop.find({'spc.are':'hanguo'});//通过子文档里面的属性来查询
4)唯一索引
db.collection.ensureIndex({filed.subfield:1/-1}, {unique:true});
5)系数索引
稀疏索引的特点------如果针对field做索引,针对不含field列的文档,将不建立索引.
与之相对,普通索引,会把该文档的field列的值认为NULL,并建索引.
适宜于: 小部分文档含有某列时.
db.collection.ensureIndex({field:1/-1},{sparse:true});
> db.tea.find();
{ "_id" : ObjectId("5275f99b87437c610023597b"), "email" : "a@163.com" }
{ "_id" : ObjectId("5275f99e87437c610023597c"), "email" : "b@163.com" }
{ "_id" : ObjectId("5275f9e887437c610023597e"), "email" : "c@163.com" }
{ "_id" : ObjectId("5275fa3887437c6100235980") }
如上内容,最后一行没有email列,
如果分别加普通索引,和稀疏索引,
对于最后一行的email分别当成null 和 忽略最后一行来处理.
根据{email:null}来查询,前者能查到,而稀疏索引查不到最后一行.
6)hash索引
哈希索引速度比普通索引快,但是,无能对范围查询进行优化.
适宜于---随机性强的散列
db.collection.ensureIndex({file:’hashed’});
7)重建索引
一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此.
可以通过索引的重建,减少索引文件碎片,并提高索引的效率.
类似mysql中的optimize table
db.collection.reIndex()
d)删除索引
1)删除单个索引
db.bar.dropIndex({title:1});
2)删除所有索引
db.bar.dropIndexes();