|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php1 b. G3 X6 v |& C7 ]) o+ U2 G
/ x! s! B: t I, P& G7 C% s3 d- use MongoDB\Driver\Manager;7 V, t) P* k# ]& a
- use MongoDB\Driver\BulkWrite;! e8 p5 l9 {5 H! {* I0 b' G
- use MongoDB\Driver\WriteConcern;2 [1 G6 [+ h9 G
- use MongoDB\Driver\Query;; d! M9 T1 Q0 e! r% T" p
- use MongoDB\Driver\Command;+ J, R9 j& _7 p* j/ A0 [
- 5 S7 i U, e6 v' `% T' ~8 Q( |
- class MongoDb {
8 k3 N Y+ Z+ a7 m& V6 v7 r
( C- M+ x! z' L# F3 D, p, j0 w- protected $mongodb;% K. E2 l/ {" x# H7 M1 ]
- protected $database;
- W* s& _5 w$ | ^$ h4 J - protected $collection;
1 e' Z! m2 Y. G1 I& _& v - protected $bulk;6 S1 Y! l) b8 m- B/ [( s3 r3 ]/ N$ r7 Q
- protected $writeConcern;! q8 b+ B4 {/ _- ~% H" A
- protected $defaultConfig
7 L8 @- q- D% ?3 n0 [ - = [% a t% I/ e2 e p7 J) L
- 'hostname' => 'localhost',
# ]5 n5 [; l4 R% M% I5 t& q - 'port' => '27017',
, Z4 h# V+ R5 E7 \/ V6 B! q+ ` - 'username' => '',
% `7 ~% F3 M$ O7 y( X - 'password' => '',! p( E& w/ d( H- B5 `/ Z
- 'database' => 'test'' O& F( z% b+ j9 [) c: ^+ E' P
- ];- M" T0 I3 |) {
- 7 C- @; O3 p8 [, d3 Y' U7 F4 m( f
- public function __construct($config) {6 T0 a/ x& J6 D- p
- $config = array_merge($this->defaultConfig, $config);
) R4 w# y( P' H# _5 L - $mongoServer = "mongodb://";! ^$ K$ }- i% e
- if ($config['username']) {
1 r H0 q5 N% k* T ~ - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
0 g% E, b* s( E, [% W, F, W+ Y - }
( t3 M: }: I: x+ b3 N - $mongoServer .= $config['hostname'];
5 l7 Z7 q6 ?; ? - if ($config['port']) {" k2 P6 ]2 ]. k2 V$ U! Y* W( V2 j
- $mongoServer .= ':' . $config['port'];! e; J! p% m* e9 f. \
- }9 c3 D- K5 P9 p- O4 t: p* V- h
- $mongoServer .= '/' . $config['database'];
( S, y6 z6 A( A& z$ n1 l% {5 W8 D
$ B- R$ R: X7 D- $this->mongodb = new Manager($mongoServer);& T5 h8 [- X# O1 l3 ]3 s1 x3 o
- $this->database = $config['database'];8 {9 Z8 _: L( M. B2 f
- $this->collection = $config['collection'];
4 K+ ^, a1 n6 Z2 M% {1 W - $this->bulk = new BulkWrite();
* r. Z8 r' |- ^' C - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);) w% f) [/ r: A; u
- }
# i9 P! c: ^& D5 v: Z - , x6 U& E% g: S7 H
- public function query($where = [], $option = []) {
2 }5 ^; V+ C6 [* l6 t! z - $query = new Query($where, $option);
* b/ S, ]# n/ `- Y& g - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
: V3 m7 A; T5 I3 Z; o - # R! R' v+ f. k t/ s# F% R
- return json_encode($result);
3 G7 @9 f9 Y% n5 L+ S. U- L4 F - }
8 h# C2 l- g! W- F$ x0 d - / R; E9 N' {+ b: w C6 p
- public function count($where = []) {" D: |, @3 D2 w+ o) F6 N
- $command = new Command(['count' => $this->collection, 'query' => $where]);5 R3 S# E3 r0 J; k, `+ p
- $result = $this->mongodb->executeCommand($this->database, $command);
9 q# N& Z% N: u5 n Z$ \7 W/ X0 Z - $res = $result->toArray();! Y5 m3 M, }6 f5 m) \, U7 U) G. ~' r
- $count = 0;. o2 I; x9 n U- Y9 d3 h/ T
- if ($res) {
' E; E$ c( B+ D2 I - $count = $res[0]->n;
% i0 c* { w( S7 m* N - }
- ]+ K; P, j6 ~! q) E
5 B( [ h# S' P# A- F- return $count;( ~9 g/ A& v8 t/ D) y- x
- }4 I, }( e0 Y7 O: {# r# Y
( r* }, A9 Q7 L# P( }- public function update($where = [], $update = [], $upsert = false) {. |' E# H5 B+ R' X
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);) O1 [1 y- o1 D4 F6 D
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);- j- X7 p6 O( ?6 j
- - H: R1 s, ] W
- return $result->getModifiedCount();& g9 _( p9 p- F+ Q( y$ P
- }, N5 n: Z4 F0 ^9 N. N
- ; M3 m" m4 U. m6 f6 {' R6 E" Y. U
- public function insert($data = []) {4 N O$ T- Q0 u# S5 d
- $this->bulk->insert($data);9 Y$ y9 l* [: V/ [
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);/ s0 m5 m5 n$ b8 z0 L+ v( }8 X
- : c) t! R" i% e6 Y" S
- return $result->getInsertedCount();
9 \/ n+ m. {* _7 ^( ] - }
) P' z+ @& e3 s& d
# |/ n. t% O) }6 C' v9 F+ a$ \- public function delete($where = [], $limit = 1) {
7 N7 I' f6 D, U+ B - $this->bulk->delete($where, ['limit' => $limit]);
' @9 d c. I+ r$ K h% d - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
' {1 N: u; r9 b. z4 Q9 Q" x1 }
7 v6 Z5 x1 m/ a1 p9 S4 f; m- return $result->getDeletedCount();
. I8 h$ Z- I; ]- s' }6 n - }6 b4 [- ?) u+ x, D* W
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- 新, e+ s; t5 U3 t* G- S/ `' v
- $resultOne = $collention->insertOne($array, $options);//单
) |6 Z' \1 P9 \' x. J4 {, R - $lastId = $resultOne->getInsertedId();
. m) ]/ F% o0 |! I2 d - $resultMany = $collention->insertMany($array, $options);//多% E, F3 \7 ~! l4 {$ B. u
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
+ P, @) {) L( l0 u' s& G) S
- $collention->update($condition, [
! L, u3 s, X9 |) Q" x. p2 `2 H - '$set' => $values1 I7 O& C4 {5 H# b
- ,[+ S3 R: `% m9 L% }; M( s
- 'multiple' => true//多条,单条false
; n! k, h8 ^& o - ]);
复制代码- 新* A7 R0 O' A/ m# W: `) M" p
- $collection->updateOne(
! ?$ T' K6 n8 a" ~' o) v) h6 c' V2 Z: ~. a5 ? - ['state' => 'ny'],% X. M( h+ V' m' F4 R
- ['$set' => ['country' => 'us']]
+ k6 \" z- \' O$ G- Z1 G - );
+ `4 K$ O4 s, S' B3 P- R6 ^7 L/ q - $updateResult = $collection->updateMany(, a/ m# B1 R! ^5 x8 f" c: D
- ['state' => 'ny'],7 l/ V. X, W4 p1 ^- v( w8 \! m
- ['$set' => ['country' => 'us']]: t9 S0 |! F. T; j5 b% ]
- ); C" ~. D% ~$ p4 W3 `6 a4 @
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
! \: S" E( v) O/ ^9 c7 o
- $cursor = $collection->find($condition, [
2 o" W# S$ e6 K! ^, p - 'name' => true//指定字段
3 s6 n. O& {7 B v2 G$ _ - ]);
6 Q" V" h( @) G N7 g - $cursor->skip(5);
" \ N0 q$ n5 n2 c" Y6 ~$ {9 J - $cursor->limit(5);
' h9 y t9 @$ c) J8 ?% x: K - $cursor->sort([' R- r) ?7 y9 m
- 'time' => -1) c, k) i6 O6 j6 K! J
- ]);
复制代码- $cursor = $collection->find($condition, [
9 k6 A% K! a3 y L1 k1 i3 G6 V - 'skip' => 5,. | W4 J4 k" c" G
- 'limit' => 5, \: {" m. ~' w9 k$ C
- 'sort' => [7 [* u8 E3 ~, n. D$ D, u5 W
- 'time' => -1
3 u5 H8 ^2 x0 ]3 }, ] I7 \3 [ - ],//排序* d% P0 _5 M( X
- 'projection' => [
" q k; j6 H& s& v4 b' L6 p - 'name' => 1//指定字段8 S6 D& A0 [0 c% O+ n6 {
- ]/ L G4 f# d5 W* p
- ]);
复制代码 5.删除- 原7 X7 e V% u `2 U- D. j! q
- $collention->remove($condition, [* m; x# I8 k% n
- 'justOne' => false//删单条2 t" {0 m: G! v% v& z% l, K
- ]);, p7 j1 h9 y$ `) h
- $collention->remove([]);//删所有
复制代码- 新
+ P9 l6 ?: Q# a( R& m- @7 w
- $result = $collention->deleteOne($condition, $options);7 \& O* m2 Q( C$ E, H5 n: D7 k
- $collention->deleteMany($condition, $options);1 Q1 v/ i; e( m
+ F: [: }0 H6 z- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([3 M+ S1 [: ?* Q
- '_id' => $tableName//我在自增表中用其它的表名作主键
& ~# p/ t2 A2 |: ~: ` - ], [$ ?3 K9 n- N9 h9 }( j
- '$inc' => ['id' => 1]//自增
b% E# u" A4 F1 p" C - ], [( g0 [6 G( Y8 h
- '_id' => 0
3 y h# q+ t+ `' m - ], [
3 ~. f5 y7 W% L9 R: B' f& { - 'new' => 1//返回修改后的结果,默认是修改前的
5 f, g- ~# A, N) y/ Q, a - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([9 x8 J$ S" \7 {0 x+ v
- '_id' => $tableName3 m# \ |6 S! K9 x" a& j
- ], [& a+ M7 g5 Q* x
- '$inc' => ['id' => 1]9 q& R! j7 k) H7 e
- ], [
1 @% z* ~" _( H$ O5 q0 w3 L' r - 'projection' => ['id' => 1],
" C! o- G! m7 q N - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
1 O0 \5 w0 `, Q) ]& ]" I! } - ]);
复制代码 , K. Y# \1 a* S
5 C4 Z( I) k# h O |