MongoDB是由C++语言编写的开源数据库系统,是一个基于分布式文件存储的非关系型数据库(NoSQL),旨在为WEB应用提供可扩展的高性能数据存储解决方案。
ThinkPHP5.0核心并不支持MongoDb,但官方提供了mongo驱动扩展,通过扩展可以很方便的和普通数据库一样使用MongoDb,本篇我们就来给大家讲解下如何安装和使用MongoDb,主要包含:
安装环境及配置
这里给大家简单介绍下最新版本的MongoDb运行环境的安装及ThinkPHP中的配置。
ThinkPHP5.0的Mongo扩展的运行环境要求如下:
-
MongoDb3.0+ -
MongoDB PHP扩展 1.0+
第一步:安装MongoDb
关于如何安装MongoDb本文不想深入探讨,相信你需要使用MongoDb的时候已经掌握了安装过程,否则也不会选择作为你的数据存储。如果你已经安装了MongoDb的话,请略过这一步。
安装最新版本的MongoDb很简单,直接到
https://www.mongodb.com/download-center 下载对应的系统安装文件,通常社区版就可以了,很多主机服务本身也提供了MongoDb支持。
安装完后,MongoDB将数据目录存储在根目录的data/db 目录下。但是这个数据目录不会主动创建,我们在安装完成后需要创建它。建议把mongodb的bin目录加入path环境变量,方便在命令行下面执行命令。
使用mongod命令启动MongoDb服务器,使用mongo命令进入MongoDb管理后台,新手推荐使用Robomongo客户端工具进行可视化管理。
在默认情况下,
mongod是监听在0.0.0.0之上的,任何客户端都可以通过27017端口直接连接,且没有认证。好处是学习阶段上手快,不过线上部署的时候一定要注意mongodb的安全配置准则,在此就不再细说了。
系统默认的文档位于system下的local,为了测试方便,我们可以创建一个demo文档集合。
第二步:安装PHP扩展(重要)
要通过PHP操作MongoDb,就需要装PHP的mongo扩展,访问 http://pecl.php.net/package/mongodb ,选择最新的版本(截至本书写作的时候最新版本为1.2.5)即可,已经支持最新的PHP7.1版本。
以windows环境为例,针对不同的PHP提供了不同的预编译版本,选择对应的版本下载解压后把php_mongodb.dll文件放入PHP安装目录下的扩展目录(通常是ext),然后在php.ini文件中添加
extension=php_mongodb.dll
重启你的web服务器后,使用phpinfo()验证是否已经支持mongodb,如果发现如图所示,说明mongodb扩展已经安装完成。
image
第三步:安装ThinkPHP5扩展
首先确认你使用的是最新版本的5.0,然后使用Composer安装:
composer require topthink/think-mongo=1.*
5.0版本的核心框架支持
think-mongo扩展的版本是1.* 版本
如果你下载的是官方提供的5.0完整版,这一步可以略过。
官方的
mongo扩展是基于PHP的新版MongoDB driver封装,而并非使用旧版的MongoClient类库,该驱动需要PHP5.4+版本。
第四步:配置mongo
在正式使用MongoDb之前,需要修改数据库配置文件中的相关参数:
// 数据库类型
'type' => '\think\mongo\Connection',
// 服务器地址
'hostname' => '127.0.0.1',
// 集合名
'database' => 'demo',
// 用户名
'username' => '',
// 密码
'password' => '',
// 端口
'hostport' => '',
默认安装的mongodb是没有用户名和密码的,可以留空。如果你的服务器安装的mongodb提供了用户名和密码认证,请自行修改。MongoDb一样支持分布式设置,设置方法和Mysql的分布式设置一致。
下面我们就来开启MongoDb的查询之旅吧。
使用查询构造器
大部分查询构造器的方法都可以直接使用,从下面的CURD示例代码可以看出和普通的数据库查询并无大的区别。
// 创建操作
Db::table('user')->insert([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com',
]);
// 查询操作
$user = Db::table('user')
->where('name', 'thinkphp')
->where('email', 'like', 'think')
->find();
dump($user);
// 更新操作
Db::table('user')
->where('name','thinkphp')
->update([
'name' => 'topthink',
]);
// 删除操作
Db::table('user')
->where('name','thinkphp')
->delete();
开启调试模式的话,一样可以在SQL日志中生成
mongo查询语句,不过该语法仅供参考,并不能严格确保在mongo中执行。
dump($user)的输出结果类似于下面:
array (size=3)
'_id' =>
object(MongoDB\BSON\ObjectID)[12]
public 'oid' => string '589461c0fc122812b4007411' (length=24)
'name' => string 'thinkphp' (length=8)
'email' => string 'thinkphp@qq.com' (length=15)
关于主键
上面的例子中,MongoDb会自动添加_id字段而且作为主键,该主键数据是一个MongoDB\BSON\ObjectID对象实例。
为了方便查询,系统做了封装,该主键的值可以直接当作字符串使用,因此下面的查询是有效的:
// 查询操作
$user = Db::table('user')
->where('_id','589461c0fc122812b4007411')
->find();
// 或者直接使用
$user = Db::table('user')
->find('589461c0fc122812b4007411');
为了保持和Mysql一致的主键命名习惯,系统提供了一个数据库配置参数pk_convert_id可以强制把_id转换为id进行操作。
// 强制把_id转换为id
'pk_convert_id' => true,
设置后,就可以把id当成_id来使用
// 查询操作
$user = Db::table('user')
->where('id','589461c0fc122812b4007411')
->find();
dump($user);
输出结果为:
array (size=3)
'name' => string 'thinkphp' (length=8)
'email' => string 'thinkphp@qq.com' (length=15)
'id' => string '589461c0fc122812b4007411' (length=24)
原来的_id已经变成id,而且是一个字符串类型。
当然,如果需要你仍然可以添加一个额外的主键
id而不使用MongoDb默认的_id字段,但并不建议这么做。
方法变化和差异
除了常规的CURD方法之外,包括value、column、setInc、setDec、setField、paginate等方法仍然被支持,更新的时候也支持data、inc和dec方法,聚合查询方法除了count方法之外其它暂时不支持。
think-mongo扩展1.6版本开始支持聚合查询,可以直接使用包括max/min/sum/avg等查询方法。
由于数据库自身的原因,以下链式方法在MongoDb中不再支持(或者无效):
| 不再支持的方法 |
|---|
| view |
| join |
| alias |
| group |
| having |
| union |
| lock |
| strict |
| sequence |
| force |
| bind |
| partition |
针对了MongoDb的特殊性增加了如下链式操作方法:
| 方法 | 描述 |
|---|---|
| skip | 设置skip |
| awaitData | 设置awaitData |
| batchSize | 设置batchSize |
| exhaust | 设置exhaust |
| modifiers | 设置modifiers |
| noCursorTimeout | 设置noCursorTimeout |
| oplogReplay | 设置oplogReplay |
| partial | 设置partial |
| maxTimeMS | 设置maxTimeMS |
| slaveOk | 设置slaveOk |
| tailable | 设置tailable |
| writeConcern | 设置writeConcern |
并且fetchPdo方法改为fetchCursor。
查询表达式
MongoDb的查询表达式和Mysql有所区别,并非完全一致。
支持的查询表达式(不区分大小写)包括:
| 表达式 | 含义 |
|---|---|
| EQ、= | 等于(=) |
| NEQ、<> | 不等于(<>) |
| GT、> | 大于(>) |
| EGT、>= | 大于等于(>=) |
| LT、< | 小于(<) |
| ELT、<= | 小于等于(<=) |
| MOD | MOD查询 |
| ALL | 满足所有条件 |
| LIKE | 模糊查询 |
| TYPE | 字段类型查询 |
| [NOT] BETWEEN | (不在)区间查询 |
| [NOT] IN | (不在)IN 查询 |
| EXISTS | 查询字段是否存在 |
| SIZE | 元素长度查询 |
| EXISTS | 查询字段是否存在 |
| EXP | 使用MongoDB\BSON\Javascript对象查询 |
| REGEX | 使用MongoDB\BSON\Regex对象查询 |
| NEAR | 经纬度查询 |
| > time | 时间比较 |
| < time | 时间比较 |
| between time | 时间比较 |
| notbetween time | 时间比较 |
使用模型查询
一样可以使用模型的CURD操作MongoDb,下面是一个使用示例。
// 创建操作
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
// 查询操作
$user = User::where('name', 'thinkphp')
->where('email', 'like', 'think')
->find();
dump($user->toArray());
// 更新操作
$user->name = 'topthink';
$user->save();
// 删除操作
$user->delete();
甚至你还可以使用模型关联操作,包括软删除功能。
Mongo原生查询
系统提供了几个基础查询方法,仅供熟悉MongoDb语法的用户使用。
query (
query)
collection:表示当前查询的集合
query:是一个\MongoDB\Driver\Query对象,详细用法可以参考官方手册
代码示例如下
$filter = [
'author' => 'bjori',
'views' => [
'$gte' => 100,
],
];
$options = [
/* Only return the following fields in the matching documents */
'projection' => [
'title' => 1,
'article' => 1,
],
/* Return the documents in descending order of views */
'sort' => [
'views' => -1
],
);
$query = new MongoDB\Driver\Query($filter, $options);
Db::query('demo.user', $query);
execute (
bulk)
collection:表示当前查询的集合
bulk:是一个\MongoDB\Driver\BulkWrite对象,详细用法可以参考官方手册
command (
dbName)
command:是一个\MongoDB\Driver\Command对象,详细用法参考官方手册
dbName:当前操作的数据库名称,留空表示当前数据库
除此之外,系统还封装了一个cmd方法可以直接执行字符串格式的mongo命令,例如:
// 列出当前的集合
$collections = Db::cmd('listCollections');
更多的mongo命令参考MongoDb官方手册。
总结
Mongo扩展提供了和核心内置数据库一般的查询体验,并且支持:
- 数据库的基本CURD操作;
- 数据库分布式;
- 模型的CURD操作;
- 模型关联操作(个别特性不支持);
- 数据库事件;
- 模型事件;
- 原生MongoDb查询语法;
上一篇:附录A:常见问题
下一篇:附录C:数据库配置清单










网友评论