使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php6 n) [) g/ U5 c) g9 H* p
2 H; Q) I& R& `" L: w8 {- use MongoDB\Driver\Manager;
9 U. O; {$ g* }; u2 {( T) B' d/ G - use MongoDB\Driver\BulkWrite;
6 f6 [+ v7 T' r( @+ X1 k - use MongoDB\Driver\WriteConcern;
- z/ u& ?8 k+ T# Y7 j - use MongoDB\Driver\Query;+ Q" Q, o7 D9 h
- use MongoDB\Driver\Command;' r* U1 R8 r% b/ A A
3 T5 x H: t/ }2 W- class MongoDb {
- ~6 \- a/ [% {% {3 f - ) v6 ?" `' _# J' G8 Y! [1 ` v% v1 j
- protected $mongodb;
; S% _; ?. ^2 n W - protected $database;
! Z6 Z& F$ g1 H+ m( d+ B$ V - protected $collection;: v* @% P, E* _6 O$ }
- protected $bulk;
7 u& i r4 q% J - protected $writeConcern;
D/ D2 u; r4 ~7 S( A - protected $defaultConfig( s3 w( X% V. R9 w' O
- = [4 s( W9 c+ l4 q4 e) e/ D# w
- 'hostname' => 'localhost',
$ n) m- B3 \' |3 L - 'port' => '27017',
) t! ~% Z( Y5 D" a; U0 t Q - 'username' => '',
* k% S1 a) w2 A W+ M7 {' A" @" r. \ - 'password' => '',* f; e% H: |9 }% `3 S) J
- 'database' => 'test'
) I" j; I/ Z, M0 q4 q5 ?% Q$ b( F - ];8 s2 I# @" V, _4 C d- z8 p
- / q; e5 J! _- a2 v
- public function __construct($config) {
1 R, h5 q5 k6 P1 L& N. H9 e& e& O - $config = array_merge($this->defaultConfig, $config);
3 l. F1 c# i& Y/ V0 L# i - $mongoServer = "mongodb://";
! v% y* ~) [: W+ ]' \, A1 R - if ($config['username']) {
9 `) p; A7 K1 c6 Y# u' x - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';+ n+ W/ j- I8 u) t! T1 @
- }, g' F! I" r+ h! f/ T
- $mongoServer .= $config['hostname'];
& V% W" {1 h7 a8 ~- p - if ($config['port']) {6 H2 |' x7 u) }3 {* {- \
- $mongoServer .= ':' . $config['port']; g' O/ L( r- _$ H7 X6 k) y
- }
2 O% V3 }* x. v# |: L$ m( F3 R" n - $mongoServer .= '/' . $config['database'];
8 @- a; @. m7 N( z - - A5 y$ o/ o/ L
- $this->mongodb = new Manager($mongoServer);0 w( D! A6 W3 k! `# S
- $this->database = $config['database'];8 p" a- R+ c& p! l4 C7 S
- $this->collection = $config['collection'];- j* }5 v7 i$ U1 u; J
- $this->bulk = new BulkWrite();9 Q/ @& y7 ~* O+ L& k
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
9 Q6 U/ S3 z8 Z3 y+ E - }
( O- L* ^6 E1 G3 z - $ s! E- L8 o4 a3 x9 u9 ?
- public function query($where = [], $option = []) {
9 H/ S- } i% w5 V+ r9 H - $query = new Query($where, $option);) ^# [% ?1 ~9 @* R) M
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);2 @5 v0 k+ u7 v6 n; T: H6 f6 i3 }
& e) A1 [- V( b$ H6 s. J; n4 Y- return json_encode($result);0 p5 s' s; N1 K5 v
- }
* j2 N: \8 z* F
7 j& B6 P( C3 a$ E) y- public function count($where = []) {
, f( r; _* @0 b8 I. E- i i - $command = new Command(['count' => $this->collection, 'query' => $where]);
% q% o' k0 T A* J; [ - $result = $this->mongodb->executeCommand($this->database, $command);2 w+ b Y) \) J: R! \4 I& W
- $res = $result->toArray();; V+ l: g/ Y7 U( M/ |( {
- $count = 0;
, j! V& J0 ]! b - if ($res) {
( s u! g9 m- V l - $count = $res[0]->n;
* W3 ~8 F' G, {, O& e- L - }
" |) x" X8 E' @' a- f' ^
" t: O2 ]& z3 T2 I/ s- return $count;
/ a) ]! ^% c3 |+ N - }/ ^+ Z: I, f% r/ M% f6 F' z
- 1 P3 ~( N: \3 q* F5 [
- public function update($where = [], $update = [], $upsert = false) {! j8 j8 i+ Z0 h6 v( I! x
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);- q5 q l9 w4 v/ s! e
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);$ X |8 ^ {; f& ]# l
( n- g9 r0 }7 j' B0 h- u j- return $result->getModifiedCount();
4 u! F: l4 w6 _6 ? - }& J/ W: L- D; P0 d% i4 u
- @2 V1 l) ~+ a* ]. W$ H! g# [
- public function insert($data = []) {! t/ V. a; U) T" a: C
- $this->bulk->insert($data);5 B( Y1 F T3 u8 W' h8 L& y/ \
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
# c" v! O- y# U! \' X3 g5 n0 ] - 8 A" e4 d4 q* B4 p( B) Z" f! N
- return $result->getInsertedCount();
# _- y2 n2 m4 X2 W( |1 Q - }
3 U2 b6 T9 t3 }$ n/ j0 x5 b( d - 7 q" j+ ?6 R% n1 p7 A1 V: D
- public function delete($where = [], $limit = 1) {; u/ W7 _2 l8 h. n3 ?: n# b
- $this->bulk->delete($where, ['limit' => $limit]);9 [- q2 y6 X4 B2 n, y, D% v
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);" C- E/ n8 S& `0 {$ j% i& x
9 F4 M0 e& h# H7 d- return $result->getDeletedCount();
# I6 q) y/ S% e5 N2 ]% W - } D( F: }" l9 @% J0 Z
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
- n- D8 R0 q; |6 U: V7 R: ^ 2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单& ^# z- ~& l$ Y; U* ~! s
- $lastId = $resultOne->getInsertedId();* W1 z6 ~3 [0 Y% S5 K& Q
- $resultMany = $collention->insertMany($array, $options);//多
/ D( u0 z3 f, r, c - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原5 B9 Y. j/ A* s& C. V0 O1 D) C+ ?6 e- K5 M
- $collention->update($condition, [( v! V$ g# K( |) w7 X9 z# O9 B- F
- '$set' => $values. j: |* [' a- N" x' e7 J& ~) o
- ,[
) ]+ J, C( B6 X! j3 _4 H' i/ M, Q - 'multiple' => true//多条,单条false
# K* L9 {3 ]6 f0 {" F2 `1 i - ]);
复制代码- $collection->updateOne(3 R+ f/ g! y8 P: ]7 k8 d# d
- ['state' => 'ny'],, N# D8 V. a3 h- n* E' W% M
- ['$set' => ['country' => 'us']]
% Q1 `7 J# P7 C0 F4 C - );. L6 h4 V3 T7 r; ]
- $updateResult = $collection->updateMany(
3 i' C% K, a9 R ^ - ['state' => 'ny'],2 `$ n2 |- H1 y0 t( A
- ['$set' => ['country' => 'us']]! Q* `. p3 \9 `+ R, R( n. k
- );; ~ f w3 a6 J
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原( T& v* N$ f; Q; H; f6 e% b7 d
- $cursor = $collection->find($condition, [4 \% h: n, J: u7 W( `* Q1 W
- 'name' => true//指定字段# f8 }: m, S( d9 F( [1 R
- ]);
* C' q# Y! a, G* e0 f( P8 e k/ t. Y - $cursor->skip(5);
8 T$ `. T( @: G% t+ \ - $cursor->limit(5);' S7 s$ ]' J( Z* e, n& @
- $cursor->sort([% F# R' @+ z' j
- 'time' => -1
* D* D! u" _ \* x2 w2 Y - ]);
复制代码- $cursor = $collection->find($condition, [
# ?$ y# t6 a% V' H - 'skip' => 5,0 p7 Q( e) y% {
- 'limit' => 5,* ]1 b( t; F Y
- 'sort' => [& Z, O: Y, B' f$ L# y
- 'time' => -1+ K7 \0 S% R; o5 m
- ],//排序
7 ~! t( R; v) M - 'projection' => [
: B2 w; I4 e* Q5 w3 k. ?' B - 'name' => 1//指定字段
1 S+ l# ]: r5 G% A, [ - ]
' B5 e( ^3 v* d - ]);
复制代码 5.删除- 原
: h6 v/ u7 F6 s. N, {" V8 X# o
- $collention->remove($condition, [; R+ M ?, |2 C% V
- 'justOne' => false//删单条% P3 w' C# e' q
- ]);
4 w; |9 q. A9 q+ c* P6 u! V7 v$ c - $collention->remove([]);//删所有
复制代码- 新
* j" E; d# S9 A/ ]7 Q$ F
- $result = $collention->deleteOne($condition, $options);/ T* C: I7 p4 \- V% @
- $collention->deleteMany($condition, $options); {! f" a2 n7 T2 I; k3 g5 }
- * F8 L. ]7 k; Y6 E! X; H
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
% d$ P. j: H# b! J2 I5 Q - '_id' => $tableName//我在自增表中用其它的表名作主键
: q. E# b9 `3 a: O) y% a - ], [/ d& r( H3 B* P, m, W6 B
- '$inc' => ['id' => 1]//自增: B2 Z1 _3 F' F3 g6 e
- ], [" `! N9 c. V% `' D7 u+ C. k
- '_id' => 07 `. I9 ~( ~( a; r& p' \3 V
- ], [
2 N2 N" L# |8 ?' H7 m - 'new' => 1//返回修改后的结果,默认是修改前的5 `$ L# A# K8 O
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
7 p1 R4 [" `3 {0 i3 Y - '_id' => $tableName* T3 P- i! T8 k
- ], [/ Z% R8 ?' |( N) o6 Y" b+ B# V; q3 z
- '$inc' => ['id' => 1]6 w6 y. K) O7 @ i" k$ p+ _ ]
- ], [$ u6 a1 K+ T& `* E q7 w5 {/ V
- 'projection' => ['id' => 1],
# R. I+ ]. y1 g% g2 _; H - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER1 m! n; B# c7 h) ]. a: A( S c
- ]);
复制代码
P7 p5 i4 N$ k- |; }, P6 `! N3 ?/ ~- A& A" r( p) ~1 \
|