使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
1 o* d A' [- S( e - / x; y9 ~! Q% C3 m
- use MongoDB\Driver\Manager;, Q2 `! }) p! q" Z# b# t
- use MongoDB\Driver\BulkWrite;
" l# l! v- \9 W6 t/ G8 }6 \ - use MongoDB\Driver\WriteConcern;9 A L& y9 w8 Z' |
- use MongoDB\Driver\Query;
5 T8 S% @- H, Q* s - use MongoDB\Driver\Command;+ Y% P7 v" P/ q
- : P0 Q+ R) s. @# ~' _1 K
- class MongoDb {
" W5 I+ S# a' r- r1 a3 ^9 d# D B2 M - / r- b9 A" D+ L5 S5 u6 Z
- protected $mongodb; p+ z( o8 ]2 o8 }# w
- protected $database;
1 c# P/ E* u, ]: W* @5 f - protected $collection;5 f5 u! v+ M# l- p/ T$ J4 L
- protected $bulk;
" I9 C% I; T! x - protected $writeConcern;0 |$ F0 ^6 ], `9 B& o- S- W) c
- protected $defaultConfig
) H4 o$ s3 Y. E - = [3 I) S/ Z1 O) E( ?" O, |
- 'hostname' => 'localhost',: D; D2 D j) o6 o8 [
- 'port' => '27017',
4 X6 Q; s* d& C; @, F - 'username' => '',/ b9 y# @8 a( i, D! V
- 'password' => '',* _! s; {3 t1 r8 U1 H) f) B' C; D
- 'database' => 'test'2 u" M+ k- E! u9 \5 A8 H
- ];
" p. @ c; \2 ~9 `- s+ w - ; S1 [2 z+ z0 ^! h
- public function __construct($config) {
2 J' p( D! C& I* ^ - $config = array_merge($this->defaultConfig, $config);
0 [3 J7 a: r; v2 Y8 J3 H - $mongoServer = "mongodb://";
" l5 Q5 k n) M5 ^: J; L& k- n - if ($config['username']) {! D" J: \9 Q1 U. \2 [3 }; C
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
5 Q, A$ y1 P1 p& ~! G) ` - }: [: D5 r( `# v
- $mongoServer .= $config['hostname'];
8 f4 ]# h$ G# V6 }6 R - if ($config['port']) {& q& m' F( h" Y( J+ L7 }* z X0 A6 y2 z
- $mongoServer .= ':' . $config['port'];
2 B& ]& t5 Y$ e, v j& E5 b - }: I6 {+ N. U |0 N4 a8 }) ?- O
- $mongoServer .= '/' . $config['database'];8 u" I5 I6 J0 U0 {6 q+ _6 ^+ F
- - [0 ~! k3 r2 v
- $this->mongodb = new Manager($mongoServer);5 x. |: @$ g2 Q! {' e/ t
- $this->database = $config['database'];+ _) n, e& X& n! K4 ?. I$ }$ X( ]
- $this->collection = $config['collection'];
7 g1 @' A- U4 R# | - $this->bulk = new BulkWrite();1 F9 ]& n/ V( ^/ L. k5 \( d; w* ^# ~8 |& F
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);! s% m4 ~: y. a% y" y1 k& \
- }
6 p& d* w) y: ^% V* D
/ x( v1 c0 z" b- public function query($where = [], $option = []) {
5 S7 H+ ~+ _( j - $query = new Query($where, $option);- y9 w3 i+ ?. {9 }% ] o
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);' P4 s% y, m0 s/ B4 x
- & E0 q+ }5 D% @3 n
- return json_encode($result);( Q& W+ E: ]. v6 o
- }7 {+ k9 S8 N, k& T
- $ F$ M) ?$ [: w4 V2 z
- public function count($where = []) {
/ R9 o( j! V- g2 n; J4 K7 G - $command = new Command(['count' => $this->collection, 'query' => $where]);
- ~1 d0 ?. ^! l3 f - $result = $this->mongodb->executeCommand($this->database, $command);- g1 ^; V# b T6 [) c* ?
- $res = $result->toArray();
0 y" \. u9 |7 ~0 K0 a; q/ D - $count = 0;" h$ Y w. ^% m) A$ S- h8 q
- if ($res) {3 E0 U) S) m6 b1 \- k
- $count = $res[0]->n;
8 W/ D5 k$ o7 I$ F. L4 [9 U* m - }1 _: t; G& x. O
- 7 ]' {" f0 d0 k f5 W1 \& v4 O
- return $count;
$ q- j- a7 z! H% P H5 W - }# o0 a) V" H, Y n6 t$ b$ k
, f7 ~+ J# ]$ W4 u" S. `5 d! R- public function update($where = [], $update = [], $upsert = false) {& y0 T! N1 I1 y# B" Y- f
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);# e8 V, n+ g r. M& J( s$ M; z
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! ?8 J* G6 U: ?% d( o$ @+ Z. s
2 N, ~" Z) o/ I& t; ^- return $result->getModifiedCount();
" k6 s/ L$ c* V5 D/ p! V9 o - }' q/ H V0 l* [4 u% Q
# I G/ z/ K6 \: t- public function insert($data = []) {" v6 e5 G& u+ U
- $this->bulk->insert($data);
6 H2 c- F( r3 p - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. S8 ~" G' b5 e, f- j8 m
- 8 e0 l& \2 i: j, E2 h. Y; K
- return $result->getInsertedCount();0 |3 [+ G5 i. J$ f9 c& i
- }
2 G$ g1 P1 d* h) B7 J$ v( f% ]
* e2 d7 I7 p! ?" t8 e; A- public function delete($where = [], $limit = 1) {
2 I' s7 x- k( m# P - $this->bulk->delete($where, ['limit' => $limit]);/ S! g* u4 g. M3 Q8 p1 t' G
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 R2 l% W- V' ]$ C" _ - " T9 t) F1 z8 e4 x3 O# ?
- return $result->getDeletedCount();
) t& K4 d" o4 u" o8 G) K I6 ^ - }. I+ w( u* W7 E& `7 F
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
( D5 J! E* p9 F1 J% P0 |' G# _
- 新5 s3 s3 K, b3 @/ [5 y# D' Q
2.新增- 原
4 O% U0 h. x! e! u& i/ i1 ?
- $collention->insert($array, $options);
复制代码- 新, W9 M8 r/ q4 g8 G8 `% U8 ?' [
- $resultOne = $collention->insertOne($array, $options);//单- D+ y) Z( j7 I' x
- $lastId = $resultOne->getInsertedId();
* I' }) I% `' ]* ~& c' ]- x* [% p4 d - $resultMany = $collention->insertMany($array, $options);//多
# U8 z( x: a. c: ?: c/ _% j, R( F# q& G - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [6 u6 U/ |$ H6 U
- '$set' => $values
O$ k# k8 Y% [* F" Y- v - ,[, d+ Y0 Y- N; x2 b. h
- 'multiple' => true//多条,单条false& [, p$ C9 ?/ n$ u1 E
- ]);
复制代码- $collection->updateOne(
$ q1 e% M5 s+ f! F' D ]5 `. w - ['state' => 'ny'],
- ~# a) v& v; c* R - ['$set' => ['country' => 'us']]6 ]/ B. w, n1 {
- );# a6 L0 y v$ }6 u( A+ u
- $updateResult = $collection->updateMany(0 o& ~* t6 C# S% Q& j
- ['state' => 'ny'],
) x1 G4 P9 R# s6 G* A - ['$set' => ['country' => 'us']]
6 Q1 i' K; V, e8 s - );
3 {4 \. J0 m/ F- K3 X, e6 u) | - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [* B2 g( B* i: c- I
- 'name' => true//指定字段, P+ E5 q6 A* q; g. ?
- ]);6 H. d [' u8 g% c: u4 `
- $cursor->skip(5);
% }9 `8 Q9 W( J/ T+ Q# V m- [# f - $cursor->limit(5);
* T. W* ]! s# j0 ~; o3 H: M - $cursor->sort([
# T. I; l+ R) W5 Y- O' ?! ~# S# n - 'time' => -1! p, Y9 e! ?" f8 d1 Q2 C7 F
- ]);
复制代码- 新
/ u) N) n; D3 A5 {: w g
- $cursor = $collection->find($condition, [7 U& Q+ C- H( ^
- 'skip' => 5, z M. Y# U; R$ j- R
- 'limit' => 5,
' T2 P I0 v. f* m2 C - 'sort' => [
9 D7 j4 w5 h6 {6 d - 'time' => -1
. A" P5 Y* O" |8 k8 L/ R2 I m. n - ],//排序: n( p9 h( w6 V( w' O
- 'projection' => [+ u. h3 M' p/ x
- 'name' => 1//指定字段0 B5 g# I* {7 F
- ]
8 [7 e) b1 {4 p8 r - ]);
复制代码 5.删除- 原
8 [) ?- r5 H7 [5 `$ x& C" h9 ^
- $collention->remove($condition, [
4 k T$ y& B+ d7 O, G( C8 x+ e. _ - 'justOne' => false//删单条# Q) c! e1 k( S5 ?( P9 q
- ]);
7 o3 Y3 |- a2 z0 ]* b5 i- X - $collention->remove([]);//删所有
复制代码- 新
; N1 \ B( d- S2 r5 O& T
- $result = $collention->deleteOne($condition, $options);
6 ?5 d- _0 g5 D. n) Q4 F - $collention->deleteMany($condition, $options);* r/ Y4 j0 f* V1 x
- ) }" Z" i. N" t$ w$ a# G
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
9 |( ^/ d2 m6 Q* @' r/ o - '_id' => $tableName//我在自增表中用其它的表名作主键
3 ~6 ]3 A7 S! p* [8 q - ], [1 H# N U7 ]- {" n
- '$inc' => ['id' => 1]//自增
/ k9 [. r" [2 r. |' V, y - ], [
+ A- P# S# @% _- a8 o - '_id' => 0: X# _3 L. W% B' y: d; q$ h: H1 D
- ], [! V# T3 i+ b t% h& x3 G
- 'new' => 1//返回修改后的结果,默认是修改前的
3 T: }) e% `1 |8 b& H6 g4 { - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
" `' w/ t" C. ~- K) T4 T: m- F - '_id' => $tableName' X" L6 ]3 _ p$ i+ ~# O3 N o8 \
- ], [
6 v1 ~/ Z: o) p( A2 B - '$inc' => ['id' => 1]
# J [8 r* g3 o$ b4 @7 q - ], [+ f, u7 h( W$ ~; A3 f2 a
- 'projection' => ['id' => 1],
2 R' c( d" [! C; ?+ c+ Z# { - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
. e! V) U8 V% N1 H% R1 {8 b - ]);
复制代码 ! o) |6 _3 F. V% g
; }1 Z6 y' U+ G7 \4 u( ^/ v |