附录B: 使用MongoDb

MongoDB 是由C++语言编写的开源数据库系统,是一个基于分布式文件存储的非关系型数据库(NoSQL),旨在为WEB应用提供可扩展的高性能数据存储解决方案。

ThinkPHP5.0核心并不支持MongoDb,但官方提供了mongo驱动扩展,通过扩展可以很方便的和普通数据库一样使用MongoDb,本篇我们就来给大家讲解下如何安装和使用MongoDb,主要包含:

  • 安装环境及配置
  • 使用查询构造器
  • 关于主键
  • 方法变化和差异
  • 查询表达式
  • 使用模型查询
  • Mongo原生查询
  • 总结

安装环境及配置

这里给大家简单介绍下最新版本的MongoDb运行环境的安装及ThinkPHP中的配置。

ThinkPHP5.0Mongo扩展的运行环境要求如下:

  • MongoDb 3.0+
  • MongoDB PHP扩展 1.0+

第一步:安装MongoDb

关于如何安装MongoDb本文不想深入探讨,相信你需要使用MongoDb的时候已经掌握了安装过程,否则也不会选择作为你的数据存储。如果你已经安装了MongoDb的话,请略过这一步。

安装最新版本的MongoDb很简单,直接到
https://www.mongodb.com/download-center 下载对应的系统安装文件,通常社区版就可以了,很多主机服务本身也提供了MongoDb支持。

安装完后,MongoDB将数据目录存储在根目录的data/db 目录下。但是这个数据目录不会主动创建,我们在安装完成后需要创建它。建议把mongodbbin目录加入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扩展已经安装完成。

附录B: 使用MongoDb_第1张图片
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' => '[email protected]',
]);

// 查询操作
$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 '[email protected]' (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 '[email protected]' (length=15)
  'id' => string '589461c0fc122812b4007411' (length=24)

原来的_id已经变成id,而且是一个字符串类型。

当然,如果需要你仍然可以添加一个额外的主键id而不使用MongoDb默认的_id字段,但并不建议这么做。

方法变化和差异

除了常规的CURD方法之外,包括valuecolumnsetIncsetDecsetFieldpaginate等方法仍然被支持,更新的时候也支持dataincdec方法,聚合查询方法除了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 = '[email protected]';
$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:数据库配置清单

你可能感兴趣的:(附录B: 使用MongoDb)