|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php* q2 ~9 l& k& _# b! \
8 V7 b5 x5 H) q6 \7 q3 u$ d G- use MongoDB\Driver\Manager;) D! G' ]( i' J* f6 N4 g
- use MongoDB\Driver\BulkWrite;' u0 F% v" @5 h G! ]3 I h/ [4 O
- use MongoDB\Driver\WriteConcern;
# K) C( n' G2 ?9 c( Z5 H" ]+ ? - use MongoDB\Driver\Query;
( q2 G) O2 G+ U+ b& t& o - use MongoDB\Driver\Command;
5 t6 F# X. v' l0 ? - # O# u- e% q8 D; V
- class MongoDb {4 d0 V0 b# u% y, G3 n
$ T+ B- V( b* p) Q- protected $mongodb;
) B' k7 l5 k: ?' C1 y* F+ {2 Y - protected $database;
2 |$ @4 i% z3 u! K) E: T+ W* ^. J3 ` r: u - protected $collection;
f2 b0 U. R0 A7 J2 k - protected $bulk;: n5 e* g6 F/ o- |1 Y# d, m2 T
- protected $writeConcern;' _. j, q4 A4 ^5 G0 f/ C: z
- protected $defaultConfig2 Z5 e1 @/ }; e+ ~7 Z: I
- = [% y5 J% [. x# |( B' p& D$ [
- 'hostname' => 'localhost',8 `2 H0 H* k1 |8 y6 K. f" P- m3 y1 M
- 'port' => '27017',
& k$ {3 |' X7 s- Q+ f - 'username' => '',$ u: F$ y8 u7 C7 s7 l! U
- 'password' => '',, X# m8 N% [5 d2 u. E+ J
- 'database' => 'test'
6 `1 P9 d6 u7 z; ^ - ];' p" e& k+ B& ]& M- S1 g
1 g S1 q) x* g6 J- public function __construct($config) {, `5 c" K+ b1 D0 W
- $config = array_merge($this->defaultConfig, $config);" P+ |% C% Z# R( r" t
- $mongoServer = "mongodb://";( `0 R% e. E! A/ H9 T% @8 {1 ?
- if ($config['username']) {
) j" F' e: |4 |7 u' \ - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
, y7 J# g- [( `, j& }* i - }
2 d% c! e+ c$ d+ d. V6 p! \ - $mongoServer .= $config['hostname'];
0 w, J; k2 s4 L, O p, Y - if ($config['port']) {( |9 s2 r$ e- v- A/ ?8 y/ @
- $mongoServer .= ':' . $config['port'];) u! O/ t/ r6 y+ ?7 z& t- }
- }
8 D* Q5 {8 _# ]$ u: z6 V - $mongoServer .= '/' . $config['database'];
5 k3 {4 ~7 X; L* S. F1 p. b: b+ T
$ M' d% d. _/ h/ p3 l* S5 W9 J- $this->mongodb = new Manager($mongoServer);. r, Z( m8 H4 H
- $this->database = $config['database'];
' V; U! v( R7 q' R( ?( d( r - $this->collection = $config['collection'];
5 _- ]- \0 j5 p* P - $this->bulk = new BulkWrite();
9 }2 F* u- f. W) E3 y - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
, C1 J- p) G4 b1 B* ` - }
- F& g8 C' K. x! D: Q
* n# i1 Q, L/ U Q3 R4 s; T$ @3 J- public function query($where = [], $option = []) {
3 q: O4 {, ]9 \ V - $query = new Query($where, $option);
$ r, D$ `+ G, ?5 R E& w - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
/ x* x* {' u% b7 P8 K - 1 ~& x- S9 R/ M8 |
- return json_encode($result);+ N$ d/ _/ n. F5 o: V# y
- }
3 w: K. z9 N* ?4 j( _ z2 G - 6 X3 E( o, ?; X8 { i
- public function count($where = []) {9 x. A: z3 b3 _- q
- $command = new Command(['count' => $this->collection, 'query' => $where]);5 H1 M5 A' f6 ]% \
- $result = $this->mongodb->executeCommand($this->database, $command);; M0 r, l9 v! Z- J( w6 E) v( g! m
- $res = $result->toArray();2 E, y, w4 d0 @* X9 c/ o
- $count = 0;
! B) `% }" l {7 | h+ P - if ($res) {
5 k! d# F U; ~ p" J/ Z - $count = $res[0]->n;/ X* M6 h; N1 I" t t1 N
- }
. f$ N% j B% }& I; [6 O
( k9 z, x2 c3 f1 R8 [+ N- return $count;
" m7 `" T- j7 `, ?4 D7 @ - }* F; M* h( ]- a& t7 W
- ! B d7 C' T' ~0 w( K2 i
- public function update($where = [], $update = [], $upsert = false) {
( P! s1 V8 f) G8 Q* |0 I - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);% A8 Z" c( q3 o$ Y$ V+ i
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 Z3 F. w) h% c* T - ' V( q7 _- l6 d, I- a
- return $result->getModifiedCount();
, C" k8 q3 R- p( J, y. l* @ x - }2 k8 E3 t F' Q2 @! U, O! W$ f
1 f% G. \2 J. ^( L* p2 Y. c- public function insert($data = []) {5 N0 K# @; w" D+ ~ R$ u6 ~4 \# @8 N
- $this->bulk->insert($data);+ H; }$ f) y. W9 l" S. A
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
! ]4 q! l0 B {& I; {
# p9 W5 B1 P; y% |7 R- return $result->getInsertedCount();
2 F$ y1 d/ o% _9 @& m# G9 k - }
9 h; z9 V. G. E' [; G
7 ]2 x/ N2 E$ |7 m- public function delete($where = [], $limit = 1) {
8 f" I: e' v' e+ k7 N - $this->bulk->delete($where, ['limit' => $limit]);3 X- x" i- B' I- O- W) O) j! x
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);5 r0 L& y$ @/ G+ V' V9 v
* L j1 m H0 |; |& \3 z- return $result->getDeletedCount();
5 A$ z: P' Y! W1 g/ g - }3 w; X* \' v& l
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原
, _# Y; t+ i) ` T3 [- T2 A! P
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
5 {; t# Q* i7 N( B! W+ ^+ x - $lastId = $resultOne->getInsertedId();
+ ~* N1 ]' E2 c' p - $resultMany = $collention->insertMany($array, $options);//多
3 a; W/ Z# m. i9 S - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原# V4 W' \7 \ d7 @7 _3 x6 _
- $collention->update($condition, [; k- b- @9 V" q8 F* k! K4 u7 d
- '$set' => $values
5 d- S! i4 f+ A! g8 `5 f - ,[
/ i' |# T( X' s& q9 F! | - 'multiple' => true//多条,单条false
; V+ g' o$ h0 p! R0 B- _2 x - ]);
复制代码- 新
! N2 a; U8 ~+ s4 R- P7 s& c
- $collection->updateOne(* N3 W) ^. U( k u2 {2 I: |
- ['state' => 'ny'],. Y2 z- u T* C. ^$ A& m. t
- ['$set' => ['country' => 'us']]) X3 X) G& _" y0 E- n3 S
- );
* H( X% w+ [% p) u - $updateResult = $collection->updateMany(
* ^8 n$ D9 e* U - ['state' => 'ny'],' V2 A. H& f- z( l
- ['$set' => ['country' => 'us']]
! x Y) o& X4 u* Q# R - );; W" T% h) A( J, ^6 r8 l3 |: A8 v
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
9 J8 M1 ~" p2 z. ]9 }4 a5 N
- $cursor = $collection->find($condition, [
, `# C C- N% u' \! Y8 ` - 'name' => true//指定字段
: q; g9 n. s" A5 ~ - ]);
4 D* n+ ^- i6 K" R - $cursor->skip(5);
3 H2 e% Z9 e$ f1 M) {; u! U - $cursor->limit(5);2 P, U3 o7 D8 h0 m7 ~9 t/ m
- $cursor->sort([
. U7 a5 [# t& L+ c6 F& D: ` - 'time' => -14 u( V- Q7 [+ A! ~8 G* S3 y
- ]);
复制代码- $cursor = $collection->find($condition, [
! b+ C3 m# s; |, D - 'skip' => 5,
s J! \; ]/ C7 i% A; ` - 'limit' => 5,
7 }( w# s w4 t4 U/ } - 'sort' => [, e2 Z, _- \7 Y7 U o& D
- 'time' => -1# }4 b5 V! F' `& s0 l- J4 R: A
- ],//排序& g, Z1 a, {! g' o
- 'projection' => [6 k. Z; ~1 [: M
- 'name' => 1//指定字段
, [- A8 [+ W1 J3 E1 b - ]5 P$ B" T% u" ?- Z4 ~7 W
- ]);
复制代码 5.删除- 原
$ v: @* H8 M7 r1 r; ^- p3 @# G+ Z: I
- $collention->remove($condition, [
" T% A8 m; i1 s/ ^ - 'justOne' => false//删单条+ X4 U9 ]# Q! w9 ~* y/ G
- ]);
! p r3 F: E) n, E6 B - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);& b; L* y+ G6 D) K8 D$ E' [: [# I% p
- $collention->deleteMany($condition, $options);9 {. i8 S, r% P5 l
' [0 T+ |+ A( O! O) U. M' L# B( `$ j m- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([) }& S, e' l* r4 ~, I! v
- '_id' => $tableName//我在自增表中用其它的表名作主键
2 T0 N0 Y0 ?# V3 {$ I9 h - ], [$ I2 f8 |- l$ b& Q! D+ @7 a0 g
- '$inc' => ['id' => 1]//自增
: N. w9 F. e) j. C1 A$ J. J% h - ], [
9 o) k1 E4 L7 Z3 M' B8 i - '_id' => 0
2 F0 F( A( }9 d - ], [
. r% e& y9 j, [3 d7 u - 'new' => 1//返回修改后的结果,默认是修改前的
6 d, }0 p7 v: \) t A) O3 T7 ^/ w( x. C - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([8 R+ X# S2 O/ ~& N0 k
- '_id' => $tableName
& U9 D. P: t5 @% } - ], [" ^! ]/ V1 B& }6 b
- '$inc' => ['id' => 1]. q F: U. w7 \/ J4 Y
- ], [
/ y2 P& H. u" Y2 v( H j) ] - 'projection' => ['id' => 1],' }* Z+ u. k( D, V
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
+ r) _ D& `- A - ]);
复制代码 ; U$ C$ d6 {8 l Q* o3 F- G
- U% h# U1 m% {! q4 B9 U |