概念 (非关系型文档)
区别 (mysql cache json)
使用 (curd 聚合)
高可用 (主从 分片)
场景 (关联低 效率高)
高级 (mapreduce gridfs)
其他 (地图 。。)
1.MySQL与MongoDB都是开源的常用数据库,mongodb以BSON结构(二进制)进行存储,对海量数据存储有着很明显的优势。下面是Mongodb与Mysql的操作命令的对比。
2.区别
BSON是由10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式。BSON基于JSON格式,选择JSON进行改造的原因主要是JSON的通用性及JSON的schemaless的特性。
BSON主要会实现以下三点目标:
1.更快的遍历速度
对JSON格式来说,太大的JSON结构会导致数据遍历非常慢。在JSON中,要跳过一个文档进行数据读取,需要对此文档进行扫描才行,需要进行麻烦的数据结构匹配,比如括号的匹配,而BSON对JSON的一大改进就是,它会将JSON的每一个元素的长度存在元素的头部,这样你只需要读取到元素长度就能直接seek到指定的点上进行读取了。
2.操作更简易
对JSON来说,数据存储是无类型的,比如你要修改基本一个值,从9到10,由于从一个字符变成了两个,所以可能其后面的所有内容都需要往后移一位才可以。而使用BSON,你可以指定这个列为数字列,那么无论数字从9长到10还是100,我们都只是在存储数字的那一位上进行修改,不会导致数据总长变大。当然,在MongoDB中,如果数字从整形增大到长整型,还是会导致数据总长变大的。
3.增加了额外的数据类型
JSON是一个很方便的数据交换格式,但是其类型比较有限。BSON在其基础上增加了“byte array”数据类型。这使得二进制的存储不再需要先base64转换后再存成JSON。大大减少了计算开销和数据大小。
当然,在有的时候,BSON相对JSON来说也并没有空间上的优势,比如对{“field”:7},在JSON的存储上7只使用了一个字节,而如果用BSON,那就是至少4个字节(32位)
目前在10gen的努力下,BSON已经有了针对多种语言的编码解码包。并且都是Apache 2 license下开源的。并且还在随着MongoDB进一步地发展。关于BSON,
作用 | MySQL | MongoDB |
|
|
|
服务器守护进程 | mysqld | mongod |
客户端工具 | mysql | mongo |
逻辑备份工具 | mysqldump | mongodump |
逻辑还原工具 | mysql | mongorestore |
数据导出工具 | mysqldump | mongoexport |
数据导入工具 | source | mongoimport |
|
| |
3.指令
1、Help查看命令提示
db.help();
db.yourColl.help();
db.youColl.find().help();
rs.help();
db; db和getName方法是一样的效果,都可以查询当前使用的数据库
1、创建一个聚集集合(table)
//判断集合是否为定容量db.collName.isCapped();
1、添加一个用户
{
user: "root",
pwd: "root",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
2、数据库认证、安全模式
1、查询所有记录
相当于:select* from users;
但是你可以设置每页显示数据的大小,用DBQuery.shellBatchSize= 50;这样每页就显示50条记录了。
2、查询去掉后的当前聚集集合中的某列的重复数据
会过滤掉name中的相同数据
相当于:select distict name from users;
相当于: select * from users where age = 22;
相当于:select * from users where age >22;
相当于:select * from users where age <22;
相当于:select * from users where age >= 25;
//相当于%%
[code]select * from users where name like ‘%mongo%';
select * from users where name like ‘mongo%';
相当于:select name, age from users;
12、查询指定列name、age数据, age > 25
相当于:select name, age from users where age >25;
降序:db.users.find().sort({age: -1});
相当于:select * from users where name = ‘zhangsan' and age = ‘22';
相当于:selecttop 5 * from users;
相当于:select * from users where id not in (
selecttop 10 * from users
);
18、or与 查询
相当于:select * from users where age = 22 or age = 25;
相当于:selecttop 1 * from users;
db.users.find().limit(1);
相当于:select count(*) from users where age >= 20;
相当于:select count(sex) from users;
1、创建索引
db.users.ensureIndex({name: 1, ts: -1});
1、添加
2、修改
相当于:update users set name = ‘changeName' where age = 25;
db.users.update({name: 'Lisi'}, {$inc: {age: 50}}, false, true);
相当于:update users set age = age + 50 where name = ‘Lisi';
db.users.update({name: 'Lisi'}, {$inc: {age: 50}, $set: {name: 'hoho'}}, false, true);
相当于:update users set age = age + 50, name = ‘hoho' where name = ‘Lisi';
query: {age: {$gte: 25}},
sort: {age: -1},
update: {$set: {name: 'a2'}, $inc: {age: 2}},
remove: true
});
db.runCommand({ findandmodify : "users",
query: {age: {$gte: 25}},
sort: {age: -1},
update: {$set: {name: 'a2'}, $inc: {age: 2}},
remove: true
});
参数 详解 默认值
query 查询过滤条件 {}
sort 如果多个文档符合查询过滤条件,将以该参数指定的排列方式选择出排在首位的对象,该对象将被操作 {}
remove 若为true,被选中对象将在返回前被删除 N/A
update 一个 修改器对象
N/A
new 若为true,将返回修改后的对象而不是原始对象。在删除操作中,该参数被忽略。 false
fields 参见Retrieving a Subset of Fields (1.5.0+)
All fields
upsert 创建新对象若查询结果为空。 示例 (1.5.4+)
false
七、语句块操作
1、简单Hello World
2、将一个对象转换成json
tojson(new Object('a'));
... db.users.save({name: "u_" + i, age: 22 + i, sex: i % 2});
... };
4、find 游标查询
> while (cursor.hasNext()) {
printjson(cursor.next());
}
while (cursor.hasNext()) { printjson(cursor.next); }
5、forEach迭代循环
6、将find游标当数组处理
cursor[4];
既然可以当做数组处理,那么就可以获得它的长度:cursor.length();或者cursor.count();
那样我们也可以用循环显示数据
> printjson(arr[2]);
8、定制我们自己的查询结果
只显示age <= 28的并且只显示age这列数据
db.users.find({age: {$lte: 28}}, {age: true}).forEach(printjson);
1、查询之前的错误信息
1、查看帮助 db.yourColl.help();
2、查询当前集合的数据条数 db.yourColl.count();
3、查看数据空间大小 db.users.dataSize();
4、得到当前聚集集合所在的db db.users.getDB();
5、得到当前聚集的状态 db.users.stats();
6、得到聚集集合总大小 db.users.totalSize();
7、聚集集合储存空间大小 db.users.storageSize();
8、Shard版本信息 db.users.getShardVersion()
9、聚集集合重命名 db.users.renameCollection("users"); 将users重命名为users
10、删除当前聚集集合 db.users.drop();
show dbs:显示数据库列表
show collections:显示当前数据库中的集合(类似关系数据库中的表)
show users:显示用户
use <db name>:切换当前数据库,这和MS-SQL里面的意思一样
db.help():显示数据库操作命令,里面有很多的命令
db.foo.help():显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令
db.foo.find():对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据)
db.foo.find( { a : 1 } ):对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1
1、操作数据库
[javascript] view plaincopy
> use mydb switched to db mydb
[javascript] view plaincopy
> db mydb
[javascript] view plaincopy
> db.docs.insert({x:1,y:1})
[javascript] view plaincopy
> db.docs.find() { "_id" : ObjectId("51de4d33b41543f9704cc936"), "x" : 1, "y" : 1 }
我们可以看到这个文档比我们添加的数据多了一项_id,其类型是ObjectId。所有的MongoDB文档都需要有_id,且它的值必须是唯一的。如果我们插入的文档中没有这一项,MongoDB在插入数据库前会自动为这个文档生成一个新的ObjectId。
[javascript] view plaincopy
> db.docs.update({x:1},{$set:{y:2}}) > db.docs.find() { "_id" : ObjectId("51de4d33b41543f9704cc936"), "x" : 1, "y" : 2 }
这里用到了$set操作,否则MongoDB的Update命令只会保留_id和需要更新的域。
[javascript] view plaincopy
> db.docs.update({x:1},{y:3}) > db.docs.find() { "_id" : ObjectId("51de4d33b41543f9704cc936"), "y" : 3 }
从这个例子我们可以看到由于我们没有使用$set,更新后的文档里{x:1}被删除了。
[javascript] view plaincopy
> db.docs.remove({y:3}) > db.docs.find() >
2、聚合操作
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。
实例
[javascript] view plaincopy
use test;
allAuthors = ["Bob", "Tom", "Lucy", "Steve", "Kate", "Lily"];
allTags = ["MongoDB", "Database", "Linux", "Windows", "Solaris", "Mac"];
for(var i=0; i<1000; i )
{ _id = i;
title = "title" i;
author = allAuthors[Math.floor(Math.random()*allAuthors.length)];
posted = new Date (2012,Math.floor(Math.random()*12), Math.floor(Math.random()*28));
pageViews = Math.floor(Math.random()*10001);
tags = allTags[Math.floor(Math.random()*allTags.length)];
db.articles.save({"_id":_id, "title":title, "author":author, "posted":posted, "pageViews":pageViews, "tags":[tags]});
db.articles.update({"_id": _id}, {$addToSet:{tags: {$each : [ allTags[Math.floor(Math.random()*allTags.length)], allTags[Math.floor(Math.random()*allTags.length)] ]}}});
} ;
[javascript] view plaincopy
{ "_id" : 0, "author" : "Steve", "pageViews" : 2606, "posted" : ISODate("2012-07-31T14:00:00Z"), "tags" : [ "MongoDB", "Mac", "Database" ], "title" : "title0" }
[javascript] view plaincopy
{ $match : { posted : { $gte : new Date(2012-7-1) } } },
2、拆分tags数组:
[javascript] view plaincopy
{ $unwind : "$tags" },
3、将拆分的文档按tags域来分组,并统计各个标签出现的次数。$group中的_id域是分组的标准。
[javascript] view plaincopy
{ $group : { _id : "$tags", total : { $sum : 1 } } },
4、将统计结果排序:
[javascript] view plaincopy
{ $sort : { _id : -1 } },
5、跳过第一条纪录:
[javascript] view plaincopy
{ $skip : 1 },
6、只输出两条结果:
[javascript] view plaincopy
{ $limit : 2 },
7、将输出结果重新命名。
[javascript] view plaincopy
{ $project : { tags : "$_id", total : 1, _id : 0 } }
[javascript] view plaincopy
db.articles.aggregate([ { $match : { posted : { $gte : new Date(2012-7-1) } } }, { $unwind : "$tags" }, { $group : { _id : "$tags", total : { $sum : 1 } } }, { $sort : { _id : -1 } }, { $skip : 1 }, { $limit : 2 }, { $project : { tags : "$_id", total : 1, _id : 0 } } ])
[javascript] view plaincopy
{ "result" : [ { "total" : 428, "tags" : "Solaris" }, { "total" : 420, "tags" : "MongoDB" } ], "ok" : 1 }
/**
* 4.PHP操作MongoDB学习笔记
*/
//simplify
/*
* MongoDB PHP
在php中使用mongodb你必须使用 mongodb的php驱动。
MongoDB PHP在各平台上的安装及驱动包下载请查看:PHP安装MongoDB扩展驱动
确保连接及选择一个数据库
为了确保正确连接,你需要指定数据库名,如果数据库在mongoDB中不存在,mongoDB会自动创建
代码片段如下:
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
创建集合
创建集合的代码片段如下:
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
$collection = $db->createCollection("mycol");
echo "Collection created succsessfully";
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
Collection created succsessfully
插入文档
在mongoDB中使用 insert() 方法插入文档:
插入文档代码片段如下:
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
$collection = $db->mycol;
echo "Collection selected succsessfully";
$document = array(
"title" => "MongoDB",
"description" => "database",
"likes" => 100,
"url" => "http://www.w3cschool.cc/mongodb/",
"by", "w3cschool.cc"
);
$collection->insert($document);
echo "Document inserted successfully";
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
Collection selected succsessfully
Document inserted successfully
查找文档
使用find() 方法来读取集合中的文档。
读取使用文档的代码片段如下:
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
$collection = $db->mycol;
echo "Collection selected succsessfully";
$cursor = $collection->find();
// 迭代显示文档标题
foreach ($cursor as $document) {
echo $document["title"] . "\n";
}
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
Collection selected succsessfully
{
"title": "MongoDB"
}
更新文档
使用 update() 方法来更新文档。
以下实例将更新文档中的标题为' MongoDB Tutorial', 代码片段如下:
<pre>
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
$collection = $db->mycol;
echo "Collection selected succsessfully";
// 更新文档
$collection->update(array("title"=>"MongoDB"), array('$set'=>array("title"=>"MongoDB Tutorial")));
echo "Document updated successfully";
// 显示更新后的文档
$cursor = $collection->find();
// 循环显示文档标题
echo "Updated document";
foreach ($cursor as $document) {
echo $document["title"] . "\n";
}
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
Collection selected succsessfully
Document updated successfully
Updated document
{
"title": "MongoDB Tutorial"
}
删除文档
使用 remove() 方法来删除文档。
以下实例中我们将移除 'title' 为 'MongoDB Tutorial' 的数据记录。, 代码片段如下:
<?php
// 连接到mongodb
$m = new MongoClient();
echo "Connection to database successfully";
// 选择一个数据库
$db = $m->mydb;
echo "Database mydb selected";
$collection = $db->mycol;
echo "Collection selected succsessfully";
// 移除文档
$collection->remove(array("title"=>"MongoDB Tutorial"),false);
echo "Documents deleted successfully";
// 显示可用文档数据
$cursor = $collection->find();
// iterate cursor to display title of documents
echo "Updated document";
foreach ($cursor as $document) {
echo $document["title"] . "\n";
}
?>
执行以上程序,输出结果如下:
Connection to database successfully
Database mydb selected
Collection selected succsessfully
Documents deleted successfully
*
*
*/
//more
//*************************
//** 连接MongoDB数据库 **//
//*************************
//格式=>("mongodb://用户名:密码 @地址:端口/默认指定数据库",参数)
$conn = new MongoClient();
//可以简写为
//$conn=new Mongo(); #连接本地主机,默认端口.
//$conn=new Mongo("172.21.15.69"); #连接远程主机
//$conn=new Mongo("xiaocai.loc:10086"); #连接指定端口远程主机
//$conn=new Mongo("xiaocai.loc",array("replicaSet"=>true)); #负载均衡
//$conn=new Mongo("xiaocai.loc",array("persist"=>"t")); #持久连接
//$conn=new Mongo("mongodb://sa:123@localhost"); #带用户名密码
//$conn=new Mongo("mongodb://localhost:27017,localhost:27018"); #连接多个服务器
//$conn=new Mongo("mongodb:///tmp/mongo-27017.sock"); #域套接字
//$conn=new Mongo("mongodb://admin_miss:miss@localhost:27017/test",array('persist'=>'p',"replicaSet"=>true)); #完整
//详细资料:http://www.php.net/manual/en/mongo.connecting.php
//*************************
//** 选择数据库与表 **//
//*************************
$db=$conn->mydb; #选择mydb数据库
//$db=$conn->selectDB("mydb"); #第二种写法
$collection=$db->column; #选择集合(选择'表')
//$collection=$db->selectCollection('column'); #第二种写法
//$collection=$conn->mydb->column; #更简洁的写法
//注意:1.数据库和集合不需要事先创建,若它们不存在则会自动创建它们.
// 2.注意错别字,你可能会无意间的创建一个新的数据库(与原先的数据库混乱).
//*************************
//** 插入文档 **//
//*************************
//**向集合中插入数据,返回bool判断是否插入成功. **/
$array=array('column_name'=>'col'.rand(100,999),'column_exp'=>'xiaocai');
$result=$collection->insert($array); #简单插入
var_dump($array);
echo "新记录ID:".$array['_id']; #MongoDB会返回一个记录标识
var_dump($result); #返回:bool(true)
//**向集合中安全插入数据,返回插入状态(数组). **/
$array=array('column_name'=>'col'.rand(100,999),'column_exp'=>'xiaocai2');
$result=$collection->insert($array); #用于等待MongoDB完成操作,以便确定是否成功.(当有大量记录插入时使用该参数会比较有用)
echo "新记录ID:".$array['_id']; #MongoDB会返回一个记录标识
var_dump($array);
#返回:array(3) { ["err"]=> NULL ["n"]=> int(0) ["ok"]=> float(1) }
/*
* *
* 完整格式:insert ( array $a [, array $options = array() ] )
* insert(array(),array('safe'=>false,'fsync'=>false,'timeout'=>10000))
* 参数:safe:默认false,是否安全写入
* fsync:默认false,是否强制插入到同步到磁盘
* timeout:超时时间(毫秒)
*
* 插入结果:{ "_id" : ObjectId("4d63552ad549a02c01000009"), "column_name" : "col770", "column_exp" : "xiaocai" }
* '_id'为主键字段,在插入是MongoDB自动添加.
*
* 注意:1.以下两次插入的为同一条记录(相同的_id),因为它们的值相同。
* $collection->insert(array('column_name'=>'xiaocai'));
* $collection->insert(array('column_name'=>'xiaocai'));
* 避免
* $collection->insert(array('column_name'=>'xiaocai'),true);
* try {
* $collection->insert(array('column_name'=>'xiaocai'),true);
* }catch(MongoCursorException $e){
* echo "Can't save the same person twice!\n";
* }
*
* 详细资料:http://www.php.net/manual/zh/mongocollection.insert.php
* *
*/
//*************************
//** 更新文档 **//
//*************************
//** 修改更新 **/
$where=array('column_name'=>'col123');
$newdata=array('column_exp'=>'GGGGGGG','column_fid'=>444);
$result=$collection->update($where,array('$set'=>$newdata)); #$set:让某节点等于给定值,类似的还有$pull $pullAll $pop $inc,在后面慢慢说明用法
/*
* 结果:
* 原数据
* {"_id":ObjectId("4d635ba2d549a02801000003"),"column_name":"col123","column_exp":"xiaocai"}
* 被替换成了
* {"_id":ObjectId("4d635ba2d549a02801000003"),"column_name":"col123","column_exp":"GGGGGGG","column_fid":444}
*/
//** 替换更新 **/
$where=array('column_name'=>'col709');
$newdata=array('column_exp'=>'HHHHHHHHH','column_fid'=>123);
$result=$collection->update($where,$newdata);
/*
* 结果:
* 原数据
* {"_id":ObjectId("4d635ba2d549a02801000003"),"column_name":"col709","column_exp":"xiaocai"}
* 被替换成了
* {"_id":ObjectId("4d635ba2d549a02801000003"),"column_exp":"HHHHHHHHH","column_fid":123}
*/
//** 批量更新 **/
$where=array('column_name'=>'col');
$newdata=array('column_exp'=>'multiple','91u'=>684435);
$result=$collection->update($where,array('$set'=>$newdata),array('multiple'=>true));
/**
* 所有'column_name'='col'都被修改
*/
//** 自动累加 **/
$where=array('91u'=>684435);
$newdata=array('column_exp'=>'edit');
$result=$collection->update($where,array('$set'=>$newdata,'$inc'=>array('91u'=>-5)));
/**
* 更新91u=684435的数据,并且91u自减5
*/
/** 删除节点 **/
//$where=array('column_name'=>'col685');
//$result=$collection->update($where,array('$unset'=>'column_exp'));
/**
* 删除节点column_exp
*/
/*
* *
mongo 版本 1.3以下
$mongoxbiao->$t_name->update($up,$arr,true);
mongo 版本 1.3及以上
//$mongoxbiao->$t_name->update($up,$arr,array('upsert'=>true));
* 完整格式:update(array $criteria, array $newobj [, array $options = array() ] )
* 注意:1.注意区分替换更新与修改更新
* 2.注意区分数据类型如 array('91u'=>'684435')与array('91u'=>684435)
* 详细资料:http://www.mongodb.org/display/DOCS/Updating#Updating-%24bit
* *
*/
//*************************
//** 删除文档 **//
//*************************
/** 清空数据库 **/
$collection->remove(array('column_name'=>'col399'));
//$collection->remove(); #清空集合
/** 删除指定MongoId **/
$id = new MongoId("4d638ea1d549a02801000011");
$collection->remove(array('_id'=>(object)$id));
/*
* *
* 使用下面的方法来匹配{"_id":ObjectId("4d638ea1d549a02801000011")},查询、更新也一样
* $id = new MongoId("4d638ea1d549a02801000011");
* array('_id'=>(object)$id)
* *
*/
//*************************
//** 查询文档 **//
//*************************
/** 查询文档中的记录数 **/
echo 'count:'.$collection->count()."<br>"; #全部
echo 'count:'.$collection->count(array('type'=>'user'))."<br>"; #可以加上条件
echo 'count:'.$collection->count(array('age'=>array('$gt'=>50,'$lte'=>74)))."<br>"; #大于50小于等于74
echo 'count:'.$collection->find()->limit(5)->skip(0)->count(true)."<br>"; #获得实际返回的结果数
/**
* 注:$gt为大于、$gte为大于等于、$lt为小于、$lte为小于等于、$ne为不等于、$exists不存在
*/
/** 集合中所有文档 **/
$cursor = $collection->find()->snapshot();
foreach ($cursor as $id => $value) {
echo "$id: "; var_dump($value); echo "<br>";
}
/**
* 注意:
* 在我们做了find()操作,获得$cursor游标之后,这个游标还是动态的.
* 换句话说,在我find()之后,到我的游标循环完成这段时间,如果再有符合条件的记录被插入到collection,那么这些记录也会被$cursor 获得.
* 如果你想在获得$cursor之后的结果集不变化,需要这样做:
* $cursor = $collection->find();
* $cursor->snapshot();
* 详见http://www.bumao.com/index.php/2010/08/mongo_php_cursor.html
*/
/** 查询一条数据 **/
$cursor = $collection->findOne();
/**
* 注意:findOne()获得结果集后不能使用snapshot(),fields()等函数;
*/
/** age,type 列不显示 **/
$cursor = $collection->find()->fields(array("age"=>false,"type"=>false));
/** 只显示user 列 **/
$cursor = $collection->find()->fields(array("user"=>true));
/**
* 我这样写会出错:$cursor->fields(array("age"=>true,"type"=>false));
*/
/** (存在type,age节点) and age!=0 and age<50 **/
$where=array('type'=>array('$exists'=>true),'age'=>array('$ne'=>0,'$lt'=>50,'$exists'=>true));
$cursor = $collection->find($where);
/** 分页获取结果集 **/
$cursor = $collection->find()->limit(5)->skip(0);
/** 排序 **/
$cursor = $collection->find()->sort(array('age'=>-1,'type'=>1)); ##1表示降序 -1表示升序,参数的先后影响排序顺序
/** 索引 **/
$collection->ensureIndex(array('age' => 1,'type'=>-1)); #1表示降序 -1表示升序
$collection->ensureIndex(array('age' => 1,'type'=>-1),array('background'=>true)); #索引的创建放在后台运行(默认是同步运行)
//$collection->ensureIndex(array('age' => 1,'type'=>-1),array('unique'=>true)); #该索引是唯一的
/**
* ensureIndex (array(),array('name'=>'索引名称','background'=true,'unique'=true))
* 详见:http://www.php.net/manual/en/mongocollection.ensureindex.php
*/
/** 取得查询结果 **/
$cursor = $collection->find();
$array=array();
foreach ($cursor as $id => $value) {
$array[]=$value;
}
//*************************
//** 文档聚类 **//
//*************************
//这东西没弄明白…
$conn->close(); #关闭连接
/*
关系型数据库与MongoDB数据存储的区别
MySql数据结构:
CREATE TABLE IF NOT EXISTS `column`(
`column_id` int(16) NOT NULL auto_increment COMMENT '主键',
`column_name` varchar(32) NOT NULL COMMENT '栏目名称',
PRIMARY KEY (`column_id`)
);
CREATE TABLE IF NOT EXISTS `article`(
`article_id` int(16) NOT NULL auto_increment COMMENT '主键',
`article_caption` varchar(15) NOT NULL COMMENT '标题',
PRIMARY KEY(`article_id`)
);
CREATE TABLE IF NOT EXISTS `article_body`(
`article_id` int(16) NOT NULL COMMENT 'article.article_id',
`body` text COMMENT '正文'
);
MongoDB数据结构:
$data=array(
'column_name' =>'default',
'article' =>array(
'article_caption' => 'xiaocai',
'body' => 'xxxxxxxxxx…'
)
);
$inc
如果记录的该节点存在,让该节点的数值加N;如果该节点不存在,让该节点值等于N
设结构记录结构为 array('a'=>1,'b'=>'t'),想让a加5,那么:
$coll->update(
array('b'=>'t'),
array('$inc'=>array('a'=>5)),
)
$set
让某节点等于给定值
设结构记录结构为 array('a'=>1,'b'=>'t'),b为加f,那么:
$coll->update(
array('a'=>1),
array('$set'=>array('b'=>'f')),
)
$unset
删除某节点
设记录结构为 array('a'=>1,'b'=>'t'),想删除b节点,那么:
$coll->update(
array('a'=>1),
array('$unset'=>'b'),
)
$push
如果对应节点是个数组,就附加一个新的值上去;不存在,就创建这个数组,并附加一个值在这个数组上;如果该节点不是数组,返回错误。
设记录结构为array('a'=>array(0=>'haha'),'b'=& gt;1),想附加新数据到节点a,那么:
$coll->update(
array('b'=>1),
array('$push'=>array('a'=>'wow')),
)
这样,该记录就会成为:array('a'=>array(0=>'haha',1=>'wow'),'b'=>1)
$pushAll
与$push类似,只是会一次附加多个数值到某节点
$addToSet
如果该阶段的数组中没有某值,就添加之
设记录结构为array('a'=>array(0=& gt;'haha'),'b'=>1),如果想附加新的数据到该节点a,那么:
$coll->update(
array('b'=>1),
array('$addToSet'=>array('a'=>'wow')),
)
如果在a节点中已经有了wow,那么就不会再添加新的,如果没有,就会为该节点添加新的item——wow。
$pop
设该记录为array('a'=>array(0=>'haha',1=& gt;'wow'),'b'=>1)
删除某数组节点的最后一个元素:
$coll->update(
array('b'=>1),
array('$pop=>array('a'=>1)),
)
删除某数组阶段的第一个元素
$coll->update(
array('b'=>1),
array('$pop=>array('a'=>-1)),
)
$pull
如果该节点是个数组,那么删除其值为value的子项,如果不是数组,会返回一个错误。
设该记录为 array('a'=>array(0=>'haha',1=>'wow'),'b'=>1),想要删除a中value为 haha的子项:
$coll->update(
array('b'=>1),
array('$pull=>array('a'=>'haha')),
)
结果为: array('a'=>array(0=>'wow'),'b'=>1)
$pullAll
与$pull类似,只是可以删除一组符合条件的记录。
*/
MongoDB (名称来自"humongous") 是一个可扩展的高性能,开源,模式自由,面向文档的数据库。它使用C++编写。MongoDB特点:
a.面向集合的存储:适合存储对象及JSON形式的数据。
b.动态查询:mongo支持丰富的查询表达方式,查询指令使用JSON形式的标记,可轻易查询文档中的内嵌的对象及数组。
c.完整的索引支持:包括文档内嵌对象及数组。mongo的查询优化器会分析查询表达式,并生成一个高效的查询计划。
d.查询监视:mongo包含一个监视工具用于分析数据库操作性能。
e.复制及自动故障转移:mongo数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移。
f.高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)。
g.自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器。
2)mongo使用场合 对象存储的,适用于网站缓存 均匀分布的非热点海量数据 高伸缩场景
mongodb的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统(丰富的功能)架起一座桥梁,集两者的优势于一身。mongo适用于以下场景:
a.网站数据:mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
b.缓存:由于性能很高,mongo也适合作为信息基础设施的缓存层。在系统重启之后,由mongo搭建的持久化缓存可以避免下层的数据源过载。
c.大尺寸、低价值的数据:使用传统的关系数据库存储一些数据时可能会比较贵,在此之前,很多程序员往往会选择传统的文件进行存储。
d.高伸缩性的场景:mongo非常适合由数十或者数百台服务器组成的数据库。
e.用于对象及JSON数据的存储:mongo的BSON数据格式非常适合文档格式化的存储及查询。
不适合的场景:事务性和复杂查询
a.高度事物性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
b.传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
c.需要SQL的问题。
3)案例:
客户信息新增功能,在新增界面上需要维护客户基本信息,客户的联系人,地址信息,客户的文档资料信息,
* 如果不考虑非结构文档附件,整个页面本身就是一个完整的JSON对象,可以只调用一次即完成整个层次化集合对象的存储,而且相当简单。
* 考虑到附件信息,即操作分为两个步骤,首先上传存储附件获取附件句柄ID,然后再存储结构化客户基本对象信息。
* 对于客户拜访记录信息,录入客户拜访记录首先肯定是要选择到具体的客户,选择到具体客户后,客户的ID信息,客户的名称信息即已经可以获取到。
* 新增加一条拜访记录也是相当简单的操作即可以完成。
再来看查询功能,首先看客户信息查询可能是一个模糊查询功能,
* 而MongoDB对模糊查询性能是比较弱的,因此尽可能的减少不必要模糊查询字段,
* 对于必须的查询字段可以在MongoDB对象中增加相应的索引信息。
* 最重要的就是基于MongoDB数据库对Join操作的支持很弱,应该在数据模型设计和查询设计上尽可能的减少不必要的对象关联操作。
* 当查询到某一个具体的客户信息后,需要查看该客户具体的拜访记录就相当简单的,只是对拜访记录表最简单的根据客户ID的一个类where操作即可完成。
* 对于客户具体的附件列表信息可以做相似的设计,即点击链接后再进入到具体的客户附件文档查看界面。
对于更新功能,基本对象的更新也相当简单,剩下的就是对于联系人信息的更新,
* 联系人信息是一个子集合对象,在这里暂时还没有看到是需要对这个子集合对象全部更新掉,还是可以做到只更新操作子集合对象中的一条记录。
* 对于更新操作,仍然需要定位到具体的ID值再进行更新。对于批量更新现在MongoDB本身也提供了相应的操作,类似批量更新客户状态操作还是很容易实现的。
以上只是一个最简单的分析,基于这种分析,以后对于类似主数据管理系统的应用完全可以迁移到MongoDB数据库来支撑。
* 另外对于记录更新不频繁,对象直接相互关联和影响小的场景也适合迁移到MongoDB数据库。
* 在NoSQL数据库的使用过程中应该尽量避开类似强一致性要求,表间关系复杂,长周期事务等场景。
*/