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:數據庫配置清單