使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php- p4 [/ `4 `* d' ~
- ( O1 y# j8 H. ^' }
- use MongoDB\Driver\Manager;- T+ T) W! w6 E
- use MongoDB\Driver\BulkWrite;
4 R" ^7 p- n9 s - use MongoDB\Driver\WriteConcern;
" ~6 q/ |+ `. Z/ R5 A' t' | - use MongoDB\Driver\Query;1 P W% e3 [; D3 D
- use MongoDB\Driver\Command;( P; ` ?" I3 i
4 p/ Z; B5 f2 [- class MongoDb { R& v- X7 X- x: Q
- - f3 L" u8 D1 @: g* f1 P9 v y
- protected $mongodb;
; D! v D) u/ v: R. w1 v% X) O - protected $database;1 t+ O, v2 g* ^$ _: ~
- protected $collection;
- d- a/ r5 W5 H9 h - protected $bulk;
1 H3 {, |6 U- g9 N# S" I+ c - protected $writeConcern;( z% K8 j; q: n3 T) t- p
- protected $defaultConfig
3 O% L# v J% m! s1 g: ^3 Z1 q - = [
+ {' O: i! B; E& R - 'hostname' => 'localhost',
. U$ ^# q( C3 i - 'port' => '27017',/ A! t1 P, G9 c& P2 G2 Z4 y
- 'username' => '',6 a8 b) L) ?0 T8 H: l) s' d
- 'password' => '',5 ~9 i3 e6 q4 i% a% \: |
- 'database' => 'test'- q' Q1 W; K4 F7 E4 A: p/ s
- ];
3 c7 G: G8 |" d* @! X
% M( i$ A b7 X1 u- public function __construct($config) {
2 }1 V( U6 ]6 q1 c' } - $config = array_merge($this->defaultConfig, $config);
$ J% N4 B" N9 b, Y2 O9 H) Z - $mongoServer = "mongodb://";5 _) _2 Q& I1 W3 m7 j: q
- if ($config['username']) {
: R6 w5 R; b$ G+ T+ a7 c - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
( e/ ?" K8 ^( R: O6 H( I - }) j4 V) E! m+ ~9 |
- $mongoServer .= $config['hostname'];; ?6 e- ?- i/ Q' p
- if ($config['port']) {8 I" v' r' {0 U
- $mongoServer .= ':' . $config['port'];
+ i% o( O3 E$ y, t* I% T' ~! T3 U - }
8 ~) u0 `# }* m' N4 A! J/ ^ - $mongoServer .= '/' . $config['database'];
& C7 J: n$ N; J - ( t$ ]4 _* m& N! N8 t
- $this->mongodb = new Manager($mongoServer);! z) q4 P, E. C' R, @
- $this->database = $config['database'];
* I8 s" R0 G- g/ B - $this->collection = $config['collection'];7 M" g3 ~. n& v: B5 t
- $this->bulk = new BulkWrite();
+ S6 P1 r- e3 c/ A6 D - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
* ?) ~* n ]; k# T9 ^ - }
$ A6 H9 F8 m2 x/ Z {& g2 Q1 |
! p, x( e/ o& w7 p) F- public function query($where = [], $option = []) {
8 ]2 Q8 O7 Z, z" B - $query = new Query($where, $option);5 K/ @: V4 `) D7 o3 h
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);8 S6 O9 ~" s" X4 q7 ^
: x" } e2 d: B# I! J! R/ z* X- return json_encode($result);9 v4 u' _* m6 \! N- F/ h
- }
y7 i. L: Z" ?; P - 8 F% N/ {- @3 _' v& `- `
- public function count($where = []) {
7 a) \" p7 C# U( k1 b- s, [ - $command = new Command(['count' => $this->collection, 'query' => $where]);
( W- r$ z* x0 q x0 [0 W - $result = $this->mongodb->executeCommand($this->database, $command);, W7 N: {' }- i" c
- $res = $result->toArray();
! H& R0 a5 z! @+ ` - $count = 0;8 _% _+ O/ ?" ^) k- z; F4 z2 ^2 C
- if ($res) {
7 l- i! m, s" s" P3 e. p4 o - $count = $res[0]->n;- R2 i$ D6 m8 {2 F) W
- }
- @% x6 `9 d% [2 p) V% y7 j8 T - : c W$ m+ f; O- b
- return $count;
" Z+ _' f" N1 U" A - }
% [& B3 @8 n, I% k' T - ; h! s* o9 @) T& w
- public function update($where = [], $update = [], $upsert = false) {
( M+ p& j- M( B; A - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);/ b: a# ^ O M# o7 c
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);" T, J: G$ z7 h% i3 m# y U @4 Y9 h6 }; L
4 h( ]8 P/ M1 m) `- return $result->getModifiedCount();
% k6 N/ g& X. t: N, H% d - }2 Y4 P6 f/ m% ~ J9 V. Y% C
! Z# }/ a0 I0 ` ^5 u- public function insert($data = []) {2 `' {/ ~6 t% y5 P, f
- $this->bulk->insert($data);
' B4 H) Z" Z0 v& O( J0 E - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);8 g* e# y( g. t# _2 Z% }
- 2 n) {/ I: C- x$ m2 U
- return $result->getInsertedCount();& t e7 D! {0 }
- }3 } @' E8 R% [, ^8 y( F: s
! O- ^) ]5 T( f2 o- public function delete($where = [], $limit = 1) {" G; h7 h7 P+ T) l5 O
- $this->bulk->delete($where, ['limit' => $limit]);
+ @! W" H7 C8 K( J+ L$ d, d - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);7 {' d+ S/ J& }0 y6 [. a& F
- 5 |3 V& }9 M! f U; M
- return $result->getDeletedCount();
; c( f% B: B" K - }
) O! Y/ R& \3 Q V - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
- r. J) K9 B4 V; P9 h! [3 k+ h 2.新增- $collention->insert($array, $options);
复制代码- 新3 h- ?3 F' R+ y! N' Y4 a4 N
- $resultOne = $collention->insertOne($array, $options);//单9 j8 y$ M& T4 g( ?9 Z# f
- $lastId = $resultOne->getInsertedId();+ M, j6 l* S" f' e. b0 u$ n9 U
- $resultMany = $collention->insertMany($array, $options);//多, }% i$ b q+ S3 l, r$ ]2 j
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [2 X) q, C: N2 m6 b7 A
- '$set' => $values1 V2 S1 F- I/ N7 j, U1 A
- ,[! k# \/ j$ A# Z8 k
- 'multiple' => true//多条,单条false
6 E& n) q3 o( z6 M5 n! F - ]);
复制代码- $collection->updateOne(
3 \) T0 p6 o8 W' [ - ['state' => 'ny'],+ ]' c" s6 x* r% l
- ['$set' => ['country' => 'us']]" p, {: W5 R4 Y6 j4 A# R
- );: s v: T0 o- J8 l+ K: X) a
- $updateResult = $collection->updateMany(
/ U; j7 g U, j K2 f( ?/ P- \ - ['state' => 'ny'],
) S+ r2 w+ i) H( i- ]( @$ G - ['$set' => ['country' => 'us']]
+ g$ c {( Q3 l6 M - );
# k% @* Y0 e& b) P4 W9 e2 R- n - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
4 g" M1 }2 g" z/ {4 @3 M$ Y
- $cursor = $collection->find($condition, [7 d5 n. H) x6 i F+ q
- 'name' => true//指定字段
! }& {/ H1 m" n+ a$ d) H - ]);
5 R: g8 c- P% f" D) Q; m% h d# n - $cursor->skip(5);
9 n4 Q0 I3 |& ]+ Q - $cursor->limit(5);8 a! Y$ j' v2 J+ |; R6 |
- $cursor->sort([
+ F, P; a6 Z, w6 x, a7 i7 K - 'time' => -1
5 o! Z, w% r9 P: Q, _* } - ]);
复制代码- 新
! L! k2 @4 ?& a, w( u7 a
- $cursor = $collection->find($condition, [: V& P2 O n5 B& `
- 'skip' => 5,5 A( [: r' X! D1 f8 s {! l
- 'limit' => 5," a8 _* o5 C5 Z: @
- 'sort' => [ a' o8 T! O7 d5 N: @: e+ W
- 'time' => -1* ]$ N7 _* {; P" r
- ],//排序
6 M7 P- v# S! o. V, F& B3 G0 T - 'projection' => [1 b- o' s9 ~$ `" x1 L& E
- 'name' => 1//指定字段2 G: Y* ]0 w5 U3 ]$ N: v4 |' y
- ]
6 O& `2 j: d, `) k8 s' w" s - ]);
复制代码 5.删除- $collention->remove($condition, [( F# o b4 o, p n! J- G
- 'justOne' => false//删单条- u+ y- O8 W4 o/ }2 C4 Y4 ]
- ]);
- x# d" P/ l/ l W- \( C% V - $collention->remove([]);//删所有
复制代码- 新
- ]: ^! X5 m/ ~/ c4 Y; a8 B
- $result = $collention->deleteOne($condition, $options);+ E& w; Y* [ \) m' [
- $collention->deleteMany($condition, $options);
! f( O" U+ y% D [3 q/ x& p( y - 5 D9 E& `- q* x% m& }* X m
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
3 K9 Y2 A% D. \( |% [0 t, \5 H$ M. C - '_id' => $tableName//我在自增表中用其它的表名作主键
, C N+ A+ n: ]! y - ], [
$ e7 |! B3 }5 `4 Y - '$inc' => ['id' => 1]//自增
' I& S% O0 _2 D' w - ], [; g2 j0 e( W9 q+ J7 z" @
- '_id' => 0# a$ c h$ g) \' \0 n7 Z- X ~
- ], [8 W! @) M( W" A) g9 c0 i6 j" s
- 'new' => 1//返回修改后的结果,默认是修改前的4 b1 ^( I- l5 S& d9 n
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([2 n; K, f5 Y/ \5 h: _9 s
- '_id' => $tableName& B0 O# H/ m3 b/ `2 h- k z: _4 v
- ], [# K0 F9 M; l5 ]! N+ E" p3 y/ C
- '$inc' => ['id' => 1]
% @# g: _& I/ d6 J4 `& k - ], [
- p- q* m! E$ e0 v/ r% d - 'projection' => ['id' => 1],
% {. | k, a5 }, g - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER7 `2 m/ \* d7 o
- ]);
复制代码 P$ r4 O# ?5 b1 x, e* y1 U+ j
3 W! v, u W4 f |