|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php$ K& Q- A7 m' }
- 8 Q9 d% [$ K4 a3 f) I( l h
- use MongoDB\Driver\Manager;6 q1 f9 t ~: Q7 z
- use MongoDB\Driver\BulkWrite;: j. S' a& G9 d+ J% _
- use MongoDB\Driver\WriteConcern;# x) [5 n% ?0 p4 I, x: x. R
- use MongoDB\Driver\Query;- n2 u( o3 e0 Z2 \3 Q
- use MongoDB\Driver\Command;* L2 |8 l, \. a. J. ]- y: y
- . {: M) u9 p. E1 i/ g
- class MongoDb {' s# E4 i& f' J/ d; k
( X( w2 b+ h2 ~6 d- protected $mongodb;' @, L( H& e3 T" ~& z! I
- protected $database;" F, W- e/ G8 T. H7 J8 N
- protected $collection;* X; e2 F+ Q; V+ q' H$ { o
- protected $bulk;/ M1 I) |4 o9 G3 y* B
- protected $writeConcern;
/ [) R$ Z7 S @' A2 V - protected $defaultConfig/ |+ S, y9 `& L" [' G8 b. z8 A
- = [
+ O7 F6 W& i! }" i% {2 N - 'hostname' => 'localhost',
0 c6 m% m" J5 j1 G# H - 'port' => '27017',
: D2 F- h+ p; w6 C5 ` - 'username' => '',
- [/ d- D! q& K4 ]6 @9 |/ M - 'password' => '',
# k" z' n* P7 C: ` - 'database' => 'test'
+ q% q2 k5 ]. m2 [ - ];
- t2 `# c D+ Q" S - * I$ H7 e) S) b% q/ a" I, _1 R
- public function __construct($config) {% U0 P& s3 T- T
- $config = array_merge($this->defaultConfig, $config);
7 E9 m5 y4 o$ F/ z5 { - $mongoServer = "mongodb://";" g. X3 B7 b I$ m
- if ($config['username']) {
; o& G- V* P, V7 J& ?4 s - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';5 K' B1 `' N y3 o; K% E
- }6 q4 m. Q" @/ w; O$ J/ a( @% v6 A* L
- $mongoServer .= $config['hostname'];& l: p( d( L: B
- if ($config['port']) {5 a2 p+ u- m6 `8 F% `5 l
- $mongoServer .= ':' . $config['port'];! f, O, q7 ]6 [/ ?
- }3 f6 G3 k4 q4 u! g7 j! z5 [. Y
- $mongoServer .= '/' . $config['database'];' S6 _) x+ C" k! t+ V
" ~$ o5 U! M! k. o+ g- $this->mongodb = new Manager($mongoServer);
2 @2 P+ G0 k, [: k/ y# s - $this->database = $config['database'];/ D+ h2 y( O, n: }' c+ }( k
- $this->collection = $config['collection'];
8 \, @: D+ A( w" C [3 t' g- Z - $this->bulk = new BulkWrite();
" b& W( m/ m( J - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);- v2 K6 _, W- E" z
- }+ E0 i+ z: h' O1 o
6 B. D" Z' a2 |1 U# g" j- public function query($where = [], $option = []) {
4 ^" p9 Y- h2 s" Z0 _1 U - $query = new Query($where, $option);
4 p; T8 Y* b: Z2 H$ y$ x - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);( i, y* Q8 V3 Q
7 d) s8 b; Y8 N9 z- L# x, Z# U- return json_encode($result);. _) z6 S; h! S3 U
- }" N% c$ c/ g+ T. D0 w
/ |! L `% \9 y( G' E9 B1 s( Y- public function count($where = []) {
) G6 w8 ]2 A- b% u2 |, j l$ ` - $command = new Command(['count' => $this->collection, 'query' => $where]);1 _$ o& x H" R$ P$ U4 |
- $result = $this->mongodb->executeCommand($this->database, $command);8 \: C2 r! T5 L" q( L9 i1 `! W
- $res = $result->toArray();
+ E% A! ]; r) W6 c4 o D6 Y7 i - $count = 0;
# Q3 t" l* W" c' {7 \$ J1 R - if ($res) {9 `; F1 F1 {+ @' u* E
- $count = $res[0]->n;; E5 _9 F% [7 j; g- M5 ]5 m0 m6 ^
- }6 \$ Z7 S7 C0 d
- 2 X0 b6 W6 g/ i
- return $count;
7 r+ |5 k5 c' r+ \2 ?, y$ x - }) G3 c# }+ u: @1 c& V/ L
; A B( x* [' O- public function update($where = [], $update = [], $upsert = false) {
) b$ o# Y; Z8 d9 M5 h - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
, k7 n x% _" g1 H - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' [9 |" w& X6 E: e4 @0 D
- ) c) b- W; }0 |. T
- return $result->getModifiedCount();- A1 B! p8 u8 h3 N+ [8 a. \! t9 I
- }
: d, ^8 W4 K. u7 H* B5 s - & d3 B+ @# a# w( U
- public function insert($data = []) {
5 l. W l3 F9 o: e( n: N7 p7 p$ M: u - $this->bulk->insert($data);# o/ ?& D/ z& `, e; M
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
- h2 c+ F1 v5 n3 L+ i
0 [; h( R5 N: }: u0 O$ U& M- return $result->getInsertedCount();; ^6 A1 z) N! n, u7 N! g ^, S
- }7 d* L5 Y, ?) |% \8 Y. m
- ) y) C/ I$ E' a# X
- public function delete($where = [], $limit = 1) {
# U |: D7 m% o9 { - $this->bulk->delete($where, ['limit' => $limit]);
+ D$ k4 K% `* R' H) Y - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! x L( M, a* u% M8 z; X6 _/ e
9 k7 g; Y: y( b1 s- return $result->getDeletedCount();
3 @ ~- J, t& t9 Q$ ?6 H - }! T4 h* V& H" I
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原
! f3 z5 y A7 O( a- {$ O
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
9 {2 b; [1 | [8 k+ ] - $lastId = $resultOne->getInsertedId();
2 M) W* H) @* q5 _9 ^ - $resultMany = $collention->insertMany($array, $options);//多( e7 v0 t6 C8 A5 Y6 |! z
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原, U& ]: ]2 L0 P0 t, b, T! M: W/ Q- s
- $collention->update($condition, [8 c) x. w) W9 f6 h
- '$set' => $values
* ]# ^6 |' P( |, \0 Q- [ - ,[& M" O. x3 |9 Q# h
- 'multiple' => true//多条,单条false6 x+ d" H; p6 e+ O) b" l. e; ~( o
- ]);
复制代码- 新& Z$ c+ u- M4 \+ n! `2 T1 L
- $collection->updateOne(# l0 Y# B E$ T! D7 B% B
- ['state' => 'ny'],
6 Y/ M: O0 Y( Q! A% U! { - ['$set' => ['country' => 'us']]( e' O6 x( b- Q# U% f" R1 l$ K
- );
. a ?& ]* b: Y: B% R5 n9 O - $updateResult = $collection->updateMany( t( f: M1 f j) A. _% `
- ['state' => 'ny']," n# o+ w$ I. {) e* t3 H
- ['$set' => ['country' => 'us']]
8 A) t$ ~9 ~, x" `! k; c0 H - );8 X: p. w4 @: p
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [" \& B+ a7 p% s. D- j7 N& M
- 'name' => true//指定字段3 T- J7 y& H! r/ \3 W1 L" m
- ]);
+ v0 d5 K/ W% k ~ - $cursor->skip(5);
0 L2 v$ u+ g) h4 O8 R+ h3 ^9 x - $cursor->limit(5);
& U; u: g* T9 Z; J - $cursor->sort([5 r5 a. e. [, n4 Y6 l
- 'time' => -1
$ I+ W( X) V+ V+ _ e* C - ]);
复制代码- $cursor = $collection->find($condition, [$ b: D' V4 Q5 k0 z$ v* a
- 'skip' => 5,
8 J' `) Q2 L, v. J - 'limit' => 5," X) W! M/ X8 L: w
- 'sort' => [
+ |+ n# P# Y2 |' ~: D - 'time' => -1
; X* p1 b4 X4 Y& Y: a7 f$ f9 U+ L2 I2 ] - ],//排序 M1 C& O, E/ X3 D
- 'projection' => [+ u# V" u- p- \ F
- 'name' => 1//指定字段; i, W$ a, _8 G1 g. u+ M: D
- ]1 R. \7 G0 t2 _- W' B* K. D- Q
- ]);
复制代码 5.删除- $collention->remove($condition, [+ i @+ }/ U. Z" W m P
- 'justOne' => false//删单条
. W5 N% m( N$ R% h - ]);: A! C+ C i* R: r: g% d: d
- $collention->remove([]);//删所有
复制代码- 新
: D& t- a" R/ t: f _6 M
- $result = $collention->deleteOne($condition, $options);
2 O# y$ L% l& C - $collention->deleteMany($condition, $options);
% v/ i3 v9 ?$ ?! }) k9 Q+ E3 |3 d - * w0 F8 Y0 Q' [- R, W
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([( C, M, ?0 T9 |4 v
- '_id' => $tableName//我在自增表中用其它的表名作主键! D! e0 h, a5 [8 s9 @. O2 ? F
- ], [
: T3 x- d* h9 `$ m - '$inc' => ['id' => 1]//自增# x- z# a/ _7 @: n3 R" i
- ], [
5 ]( c3 f* Z: h& ]! ?1 e - '_id' => 00 o; c* q: h+ d1 S
- ], [
; r5 L. j, x9 \' Q8 K - 'new' => 1//返回修改后的结果,默认是修改前的
, u4 h4 O) L/ E - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([5 ~! M6 Q! N* @% s
- '_id' => $tableName
$ C) L. s/ G1 S5 w - ], [, }: X. f# s3 g& S8 t+ c, x
- '$inc' => ['id' => 1]" c' I% N" E D" k
- ], [3 U- h- d# B4 y! F/ X
- 'projection' => ['id' => 1],1 ~8 w0 X+ d7 X0 ]
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER7 X1 k7 s, l- j9 o
- ]);
复制代码
/ w9 ]6 B1 m$ v* v% v* D
# C5 q7 |" m, ?7 V |