邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

php使用mongo的GridFS存储文件
<?php
    //php使用mongo的GridFS存储文件
    $conn = new MongoClient();
    $db = $conn->photos;
    $collection = $db->getGridFS();

    //存储文件
    $id = $collection->storeFile('./logo22.png');

    //存储文件二进制流
//    $data = file_get_contents('./logo22.png');
//    $id = $collection->storeBytes($data,array('param'=>'logo图片'));

    //保存
    //$id = $collection->storeUpload('upfile');
    //相当于
    //$id = $collection->storeFile($_FILES['upfile']['tmp_name']);

    //读取
    $logo = $collection->findOne(array('_id'=>$id));
    header('Content-type:image/png');//输出图片头
    //var_dump($logo);
    echo $logo->getBytes();

回顾mongo索引

测试索引

新建50万条数据
for(var i=0;i<500000;i++){db.myusers.insert({"i":i,"username":"user"+i,"age":Math.floor(Math.random()*120),"created":new Date()});}
db.myusers.find({username:"user111"}).explain(true)
{
............
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 238,//-------------
"totalKeysExamined" : 0,
"totalDocsExamined" : 500000,//-------------
"executionStages" : {
"stage" : "COLLSCAN",//-------------
"filter" : {
"username" : {
"$eq" : "user111"
},
..............
}

增加索引
db.myusers.createIndex({"username":1})
好处:提高查询效率
坏处:数据增删改时会变慢
限制:每个集合最多64个索引
db.myusers.find({username:"user111"}).explain(true)
{
.................
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0, //-------------
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,//-------------
"executionStages" : {
"stage" : "FETCH",//-------------
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
..................
}


复合索引
索引--{"age":1,"username":1}
db.myusers.find({"age":21}) 高效
db.myusers.find({"age":21}).sort({"username":-1})高效
db.myusers.find({"age":{"$gte":21,"$lte":30}})高效
db.myusers.find({"age":{"$gte":21,"$lte":30}}).sort({"username":-1})一般


特殊索引
创建一个固定集合,最大1000字节,最多100个文档,超过后会自动删除最老的文档
db.createCollection('my_collection',{'capped':true,'size':1000,'max':'100'})

TTL索引
在lastUpdated字段建立TTL索引,当服务器时间比该字段存储的日期类型时间晚86400秒之后,文档立即删除。
Mongodb每分钟对ttl索引执行一次清理
db.my_collection.createIndex({"lastUpdated":1},{"expireAfterSecs":86400})


地理空间索引
2dsphere,用于球体表面,使用GeoJSON格式(geojson.org)

{'name':'Sjm','loc':{'type':'Point','coordinates':[116.34,40.02]}}
线
{'name':'River','loc':{'type':'Line','coordinates':[[0,1],[0,2],[1,2]]}}

{'name':'Beijing','loc':{'type':'Polygon','coordinates':[[2,1],[2,2],[4,2]]}}

创建索引
db.world.createIndex({'loc':'2dsphere'})
查询
var littleVillage={
'type':'Polygon',
'coordinates':[[-70,30],[-71,40],[-70,38],[-71,40]]
}
与littleVillage有交集的区域的文档:
db.world.find({'loc':{'$geoIntersects':{'$geometry':littleVillage}}})
完全包含在littleVillage区域的文档
db.world.find({'loc':{'$within':{'$geometry':littleVillage}}})
littleVillage区域附近的文档

db.world.find({'loc':{'$near':{'$geometry':littleVillage}}})


mongodb日志太大问题

MongoDB的日志文件在设置 logappend=true 的情况下,会不断向同一日志文件追加的,时间长了,自然变得非常大。
解决如下:(特别注意:启动的时候必须是--logpath指定了log路径的)
用mongo连接到服务端

use admin  //切换到admin数据库
db.runCommand({logRotate:1})

这样会使mongo关闭当前日志文件,重启一个新的日志文件,不需要停止mongodb服务。

如果感觉之前的log日志文件无用,可以删除掉,这样能节省很大的硬盘空间。
mongo提示Cannot natively represent the long 1476355233494 on this platform
今天用rockmongo打开一个集合的时候提示

Cannot natively represent the long 1476355233494 on this platform

解决办法

在index.php中加入
ini_set('mongo.long_as_object', 1);
mongo索引学习笔记

db.imooc_collection.getIndexes() //查询索引
db.imooc_collection.ensureIndex({x:1}) //增加索引
db.imooc_collection.dropIndex({x:1}) //删除索引


mongodb索引种类
_id索引 绝大多数集合默认建立的索引

单键索引 最普通的索引 
db.imooc_collection.ensureIndex({x:1})

多键索引,与单键索引创建形式相同。区别在于字段的值
单键索引:值为一个单一的值,如字符串,数字或者日期
多键索引:值具有多个记录,例如数组 
db.imooc_collection.ensureIndex({x:[1,2,3,4,5]})

复合索引,当我们查询条件不只一条时,就需要建立复合索引
插入{x:1,y:2,z:3}
db.imooc_collection.ensureIndex({x:1,y:1})


过期索引 在一段时候后会过期的索引,索引过期,相应的数据会自动删除。这适合存储一些在一段时间
之后会失效的数据,比如用户的登录信息,存储的日志。
db.imooc_collection.ensureIndex({time:1},{expireAfterSeconds:10})
db.imooc_collection.ensureIndex({time:new Date()})
存储在过期索引字段的值必须是指定的时间类型
说明:1必须是ISODate或者ISODate数组,不能使用时间戳,否则不能自动删除
2.如果指定了ISODate数组,则按照最小的时间进行删除
3.过期索引不能是复合索引
4.删除时间不是精确。说明:删除过程是由后台程序每60s跑一次,而且删除也需要一些时间,所以存在很差。

全文索引 对字符串与字符串数组创建全文可搜索的索引
适用情况{author:"",title:":",article:""}
db.articles.ensureIndex({key:"text"})
db.articles.ensureIndex({key_1:"text",key_2:"text"})
db.articles.ensureIndex({"$**":"text"})

db.articles.find({$text:{$search:"coffee"}})
db.articles.find({$text:{$search:"aa bb cc"}})
db.articles.find({$text:{$search:"aa bb -cc"}}) //不包含cc的
db.articles.find({$text:{$search:"\"aa\"bb cc"}}) // 既包含aa又包含bb的、

全文索引相似度
$meta操作符:{score:{$meta:"textScore"}}
写在查询条件后面可以返回返回结果的相似度。与sort一起使用,可以达到很好的实用效果。
db.articles.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).score({score:{$meta:"textScore"}})
限制:全文索引非常强大,但是同样存在限制。每次查询,只能指定一个$text查询。$text查询中不能使用$nor查询中
查询中如果包含了$text,hint不再起作用;不支持中文。

索引属性:
创建索引时的格式:
db.collection.ensureIndex({param},{param}) 其中第二个参数便是索引的属性
比较重要的属性:名字 唯一性 稀疏性 是否定时删除
db.imooc_collection.ensureIndex({x:1,y:1,z:1,m:1},{name:"normal_index"})
唯一性,unique指定
db.imooc_collection.ensureIndex({},{unique:true/false})
稀疏性,sparse指定:
db.imooc_collection.ensureIndex({},{sparse:true/false})
是否定时删除,expireAfterSeconds指定:
TTL,过期索引

地理位置索引
概念:将一些点的位置存储在mongodb中,创建索引后,可以按照位置来查找其他点。
查找方式:
1.查找距离某个点一定距离内的点 2.查找包含在某区域内的点。
子分类:2d索引,用于存储和查找平面上的点。
创建方式:db.imooc_collection.ensureIndex({"w":"2d"})
位置表示方式:经纬度【经度,纬度】 取值范围:经度【-180,180】 纬度【-90,90】
查询方式:1.$near查询:查询距离某个点最近的点。2.$geoWithin查询:查询某个形状内的点。
形状的表示:1.$box:矩形,使用 {$box:[[<x1>,<y1>],[<x2>,<y2>]]}表示
2。$center 圆形,使用{$center:[[<x1>,<y1>],r]}
3. $polygon 多边形 使用{$polygon:[[<x1>,<y1>],[<x2>,<y2>],[<x3>,<y3>]]}表示 
db.imooc_collection.find({w:{$near:[1,1]}})
db.imooc_collection.find({w:{$near:[1,1],$maxDistance:10,$minDistance:3}})

geoNear查询
geoNear使用runCommand命令进行使用,常用使用如下
db.runCommand({geoNear:<collection>,near:[x,y],minDistance:(对2d索引无效),maxDistance:,num:}})

2dsphere索引,用于存储和查找球面上的点。
概念:球面地理位置索引
创建方式:db.imooc_collection.ensureIndex({w:"2dsphere"})
位置表示方式:
GeoJSON:描述一个点,一条直线,多边形等形状
格式:{type:"",coordinates:[<coordinates>]}
查询方式与2d索引查询方式类似:
支持$minDistance与$maxDistance

索引构建情况分析
索引好处:加快索引相关的查询,不好处:增加磁盘空间消耗,降低写入性能。

如何评判当前索引构建情况
1.mongostat工具介绍,查看mongodb运行状态的程序
使用说明:mongostat -h127.0.0.1:27017
字段说明:索引情况:idx miss
2.profile集合介绍
db.getProfilingStatus() //profile默认是关闭的 db.ProfilingLevel()
db.setProfilingLevel(2) //开启
db.system.profile.find().sort({$natural:-1})//查询profile日志,字段意义:ts 时间戳 info 具体的操作 milis 操作所花时间,毫秒

3.日志介绍
4.explain分析

db.imooc_collection.find().explain()

mongo的基本操作(包括php的)

db.test.find()<==> select *from test
db.test.find({'name':'foobar'})<==> select * from test where name='foobar'
db.test.find({'ID':10}).count()<==> select count(*) from test where ID=10
db.test.find().skip(10).limit(20)<==> select * from test limit 10,20
db.test.find({'ID':{$in:[25,35,45]}})<==> select * from test where ID in (25,35,45)
db.test.find().sort({'ID':-1})  <==> select * from test order by ID desc
db.test.distinct('name',{'ID':{$lt:20}})  <==> select distinct(name) from testwhere ID<20
db.test.group({key:{'name':true},cond:{'name':'foo'},reduce:function(obj,prev){prev.msum+=obj.marks;},initial:{msum:0}})  <==> select name,sum(marks) from testgroup by name
db.test.find('this.ID<20',{name:1})  <==> select name from test where ID<20
<?php
$m = new MongoClient();
$db = $m->selectDB('test');
$collection = new MongoCollection($db, 'produce');
// search for fruits
$fruitQuery = array('Type' => 'Fruit');
$cursor = $collection->find($fruitQuery);//
// search for documents where 5 < x < 20
$rangeQuery = array('x' => array( '$gt' => 5, '$lt' => 20 ));
$cursor = $collection->find($rangeQuery);
//
$js = "function() {
return this.name == 'Joe' || this.age == 50;
}";
$cursor = $collection->find(array('$where' => $js))
//where name in ()
$cursor = $collection->find(array(
'name' => array('$in' => array('Joe', 'Wendy'))
));
?>

db.test.insert({'name':'foobar','age':25})<==>insert into test ('name','age') values('foobar',25)
<?php
$collection->insert(array('x' => 1));
?>

db.test.remove({})<==> delete * from test
db.test.remove({'age':20})<==>delete test where age=20
db.test.remove({'age':{$lt:20}})<==> delete test where age<20
db.test.remove({'age':{$lte:20}})<==> delete test where age<=20
db.test.remove({'age':{$gt:20}})<==> delete test where age>20
db.test.remove({'age':{$gte:20}})<==> delete test where age>=20
db.test.remove({'age':{$ne:20}})<==> delete test where age!=20
<?php
$radioactive->remove(array('type' => 94), array("justOne" => true));
?>

db.test.update({'name':'foobar'},{$set:{'age':36}})<==> update test set age=36 where name='foobar'
db.test.update({'name':'foobar'},{$inc:{'age':3}})<==> update test set age = age+3 where name='foobar'
<?php
$newdata = array('$set' => array("address" => "1 Smith Lane"));
$c->update(array("firstname" => "Bob"), $newdata);
?>

db.imooc_collection.update({x:1},{x:999}) //把x=1的改成x=999的,只更新一条
db.imooc_collection.update({x:1},{$set:{y:100}}) //单个字段更新
db.imooc_collection.update({x:999},{x:777},true) //更新数据,如果不存在,创建
db.imooc_collection.update({x:999},{$set{x:777}},false,true) 更新多条
db.imooc_collection.remove({x:777}) //删除x=777
db.imooc_collection.drop() //删除表imooc_collection
db.imooc_collection.getIndexes() //查询索引
db.imooc_collection.ensureIndex({x:1}) //增加索引


优惠券
广告位-淘宝
最新微语