|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
! f. X8 q u+ n - : o4 l" q+ f3 l0 e8 @* O. ?
- use MongoDB\Driver\Manager; C8 i, H! C; [4 t+ ~0 d
- use MongoDB\Driver\BulkWrite;
( J" A) Z6 `0 B& q n - use MongoDB\Driver\WriteConcern;) N( g2 y" {$ ` l! c
- use MongoDB\Driver\Query;) @/ H, L# ?+ c. C4 m
- use MongoDB\Driver\Command;
$ Q2 v; f/ Q8 |7 r3 v8 S - 7 R" W9 A3 B$ M2 s- l% y
- class MongoDb {& A2 R! j4 ^7 X, H
+ n% I L: {" p$ a; y8 _- protected $mongodb;6 }9 X, s: d: n6 C1 D
- protected $database;
% \) x1 k4 e7 S1 i& a' \ - protected $collection;
) ]: ]' z6 ~6 T7 y - protected $bulk;! C" P* }- l: z) u7 `2 I. N1 s0 J0 j- |2 O
- protected $writeConcern;
' x ]+ ~) ~7 u3 [2 L - protected $defaultConfig
- C# Z7 b# B- k/ a% l - = [: H1 h/ i# V( E9 R
- 'hostname' => 'localhost',7 O/ ]6 }* a' m: {, k* o
- 'port' => '27017',
$ U! z/ [8 X) N! q - 'username' => '',, n" l" ~3 C- `" I. K9 I
- 'password' => '',
* e- Z2 W, A9 }5 N - 'database' => 'test'
* C: T( ~5 d6 j; h% H6 Z - ];
0 N8 N! |4 ]* w; U& [2 J
3 W$ g" `( A$ U* l" ], r0 D- public function __construct($config) {
5 f% I% g7 a% l6 l; I! D" J5 E7 ` - $config = array_merge($this->defaultConfig, $config);. M1 Q3 m5 p! x+ `8 j% }5 |: N0 W
- $mongoServer = "mongodb://"; U3 w. L/ U) i, c8 g7 D
- if ($config['username']) {
! j, l' m5 u: @* ` - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
" n$ Z# K8 s# W) p$ z - }5 D- W& T+ i; P7 y- U
- $mongoServer .= $config['hostname'];0 ?% P8 f$ |/ \& ]* w1 m
- if ($config['port']) {# j7 u" d+ s0 e9 s6 m) R
- $mongoServer .= ':' . $config['port'];: k! F6 R! {' F5 C
- }/ k: @, u* i, C0 Q$ a
- $mongoServer .= '/' . $config['database'];
0 m' i' b# D! J* R - . K* L. U$ h4 a! G9 K+ J
- $this->mongodb = new Manager($mongoServer);1 Y/ J( j0 Y& Q& v) ^) J# c
- $this->database = $config['database'];
3 m8 z& c( z; P# A - $this->collection = $config['collection'];
0 `) `: Y" S; _; i3 O - $this->bulk = new BulkWrite();& m# U8 G: W& ?5 f+ F
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
- u/ B8 v8 t( g7 S - }
1 e, W$ D3 g% f; ~9 A7 i, ` - 3 u7 w2 z4 n$ G
- public function query($where = [], $option = []) {' }0 e( L! t \" x) r) U
- $query = new Query($where, $option);
+ i' x2 b4 {* j- H" K( L - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
2 O0 s; T% c( I. X6 a% ]) D& s
4 Y5 t' P6 }2 H1 d% n- return json_encode($result);& C$ Y% s7 a" j+ H/ H
- }
% K; k& {& G" l3 W - ! J' _- s0 G0 t! i
- public function count($where = []) {
. n1 B# N4 m8 z% }+ B- i+ p - $command = new Command(['count' => $this->collection, 'query' => $where]);& \; T9 ^1 C6 Y5 z" G! P1 A+ e
- $result = $this->mongodb->executeCommand($this->database, $command);( V' K* c# w, n& K6 K0 k2 m
- $res = $result->toArray();3 M" V' e2 R; b
- $count = 0;3 c- V& u2 G/ J; m" h/ }7 _- f z
- if ($res) {, @& h8 n2 j5 L" Q- K4 Z
- $count = $res[0]->n;- Q$ D! X+ T: A7 x
- }( W& @0 ~- s E
- * j m) g. A+ u& I* @4 Y3 F
- return $count;0 r+ {' \4 n" z8 k% g6 X
- }- s/ U; h: P% `
; n! V2 e; D( G ]* e4 f0 H- public function update($where = [], $update = [], $upsert = false) {4 a1 \1 w7 Y5 n
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
2 R" x7 F0 O# [! W* d' O - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
1 V4 O) y0 y% k) Q. [% _ - , \4 }2 M! C3 h; s; W; ^
- return $result->getModifiedCount();
9 e3 O7 o( T7 Y7 F# p F - }/ p5 q6 [0 e* \4 P8 C; s( [
- : T$ s7 q' _5 P
- public function insert($data = []) {( D7 Z5 I& ?& C
- $this->bulk->insert($data);
7 h! C7 ~ g: E- u7 m4 ^8 h& @; F - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);4 }3 {1 u) G: P H/ L, |2 n
- # h0 V m4 ^# g6 k5 N) @. |
- return $result->getInsertedCount();
) V. v1 P; g/ |- y - }
( Z! ^. Q5 J8 f3 u% o# K - * O9 c) V! \8 |5 a. i* r7 V, [
- public function delete($where = [], $limit = 1) {7 t. X& `% n z) y& l
- $this->bulk->delete($where, ['limit' => $limit]);
4 r: W) u* Z2 ]5 u1 L - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# |" V8 e6 I% `6 S4 d4 F( T
/ k4 [1 I! ?( m9 Q) X6 P2 x- l- return $result->getDeletedCount();
0 ~" D3 ^- f7 E# O( t- F - }% T+ a( _8 g: g/ p
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原3 G+ M* |! L) m& p+ U5 W3 W
- 新
: V- t. |$ G6 E- Y8 J* q 2.新增- 原6 m1 C/ Y3 \* b9 Z/ k4 Y
- $collention->insert($array, $options);
复制代码- 新& ~5 l; b0 o! I% I7 I+ F
- $resultOne = $collention->insertOne($array, $options);//单% R$ A8 c1 z0 ?4 {
- $lastId = $resultOne->getInsertedId();
! N6 N9 g6 E9 a3 N - $resultMany = $collention->insertMany($array, $options);//多
7 P" L1 N. i( b) n* h( S) ? - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
' V6 J: a/ P: [& c# k6 v$ k# a6 k
- $collention->update($condition, [* I4 t% Y0 Z) h) I2 n+ x5 q
- '$set' => $values0 J8 C/ |' A; J* z" r& Q
- ,[
! W! ~- k. c. j2 \8 }$ D - 'multiple' => true//多条,单条false( e6 P' w. N2 ^3 j& I
- ]);
复制代码- $collection->updateOne(7 G& w/ n4 O+ I8 `
- ['state' => 'ny'],
2 } E* `1 e+ U9 p: C - ['$set' => ['country' => 'us']]0 C: t( C2 ]+ i1 L8 r8 v& X7 W. v
- );7 W- c' ]+ [: t/ U% s
- $updateResult = $collection->updateMany(, J9 y$ e& `! S6 F
- ['state' => 'ny'],
s f3 I# g9 |. q* C! w+ l) J9 I - ['$set' => ['country' => 'us']]
9 T. ?' e; k7 L$ n. y6 ]' J5 A - );1 L0 p7 |7 t; B% l
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [5 v; B8 F4 M# d' v( L
- 'name' => true//指定字段% H, K/ B/ x7 F
- ]);
: E `+ X0 Z; p - $cursor->skip(5);) B4 X S$ r7 ~" p" i
- $cursor->limit(5);2 o. }% B/ f& b6 f8 K/ x! ]; }
- $cursor->sort([
- O) i( P s" E$ Q3 w, c2 X - 'time' => -18 n# A. S' E! H/ a; F
- ]);
复制代码- 新
0 u q5 _: L, n; U" c) p
- $cursor = $collection->find($condition, [! i, n% g$ z2 |4 D* V! D- e3 O1 R
- 'skip' => 5,
3 c. K7 r, D0 n G" I( V" K - 'limit' => 5,
5 f. U! r' T( g0 V. u; d# F5 g - 'sort' => [
# o. \4 q- Q0 W5 d+ d, s - 'time' => -1( L/ H( [- O6 W! X$ Y) O
- ],//排序* m1 ^. a! d! i1 P8 r4 R! I7 q8 ^
- 'projection' => [
: I4 ~' t. S$ R: u; |8 X - 'name' => 1//指定字段0 @ O0 v6 t/ \0 ^: `) ^2 a
- ]
X: c1 |7 z! \, Q/ u - ]);
复制代码 5.删除- 原4 J3 D" Z& r( P" l6 U* \3 w( A$ F
- $collention->remove($condition, [# ?& z$ Y" R9 L/ L
- 'justOne' => false//删单条
% T' q+ I( S6 A7 L( d3 x - ]);
+ U' b& g/ _8 K9 Y - $collention->remove([]);//删所有
复制代码- 新 Y4 k9 o% t% n; D$ n' _# N/ u
- $result = $collention->deleteOne($condition, $options);* `$ ~9 t3 H3 m2 A- {9 i6 Z9 w6 t5 i
- $collention->deleteMany($condition, $options);- e& g. B9 x& ~" r0 j" B9 G
/ T6 {& ~# ^' u- k$ p0 h- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([- B; W; J3 v8 z" U
- '_id' => $tableName//我在自增表中用其它的表名作主键
2 m, E1 W/ T; k# W8 w' u2 M - ], [& \2 e6 F6 F9 V& Z" c) j& c
- '$inc' => ['id' => 1]//自增" e+ m; z0 x1 L9 s3 v; y4 A2 y
- ], [
) M0 ?4 p* Y% V - '_id' => 06 A- m/ ~3 U! r: B- h. M/ [, y
- ], [/ j0 l) T4 S% N$ T' Q- ~' Y9 R
- 'new' => 1//返回修改后的结果,默认是修改前的2 Z' T( ^8 T5 F0 R
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
7 Z' a1 U# _6 h/ y8 M. J - '_id' => $tableName7 v2 k& v; y3 H q; U9 O" O; h
- ], [8 z2 M6 _, Z( K6 H3 s6 [$ x' E0 k
- '$inc' => ['id' => 1]$ `4 w& m4 r, n# U( i: ?
- ], [
$ f' F" u8 j% y - 'projection' => ['id' => 1],% n. I2 X% M9 G# w" B' B7 w8 d! d
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER q# P# L- [3 e B
- ]);
复制代码 0 E' M% [9 V2 B2 @! l& \5 T
! d7 t9 I9 ^) u; `9 U
|