MongoDB
是由C++
语言编写的开源数据库系统,是一个基于分布式文件存储的非关系型数据库(NoSQL
),旨在为WEB应用提供可扩展的高性能数据存储解决方案。
ThinkPHP5.0
核心并不支持MongoDb
,但官方提供了mongo
驱动扩展,通过扩展可以很方便的和普通数据库一样使用MongoDb
,本篇我们就来给大家讲解下如何安装和使用MongoDb
,主要包含:
安装环境及配置
这里给大家简单介绍下最新版本的MongoDb
运行环境的安装及ThinkPHP中的配置。
ThinkPHP5.0
的Mongo
扩展的运行环境要求如下:
-
MongoDb
3.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
扩展已经安装完成。
第三步:安装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:数据库配置清单