|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
% D) r. p: H- }. g+ i8 r0 W - 1 f/ d' `5 B' A* A9 `6 c0 G
- use MongoDB\Driver\Manager;
" [/ F4 l; u) W( H+ I, C) n - use MongoDB\Driver\BulkWrite;
7 |; g: T% g: a L4 _1 I# a! m - use MongoDB\Driver\WriteConcern;
) M, W! \4 _. v! Y: j - use MongoDB\Driver\Query;
1 W0 W n- E U; g - use MongoDB\Driver\Command;
/ s, A6 |- U! s( u, @/ ]% h9 N8 M - : y k# ^: C) e; r
- class MongoDb {
; ]5 f' f3 [' g6 H4 V3 N2 [ - 5 j8 ?+ W% w" l& ~. `! w# U
- protected $mongodb;# T2 {+ E$ J4 u3 n/ S, \
- protected $database;& y1 @; T, z6 I/ b4 c5 j
- protected $collection;3 ^4 O% ?& Z, j* U9 y6 U: ?& [
- protected $bulk;+ s3 F! m" F" W7 n" l& Y
- protected $writeConcern;! X/ _0 P- x- ]& O- i: x1 n
- protected $defaultConfig
: b/ X+ K9 p( P/ U6 x. L; e: G - = [
4 {$ G* u- j. g( L2 z1 A: t1 `( R, W3 e - 'hostname' => 'localhost',. |; y/ u! ?$ r7 W: ?% Q* s _/ ]4 H7 U
- 'port' => '27017',' i, _5 c9 W# Y$ S: l3 `
- 'username' => '',; v* ]' l& B* _2 ~% _+ J: l& }
- 'password' => '',
8 r, q0 E& B9 l1 T9 N! l - 'database' => 'test'
% a( y4 H* k b$ @5 I; n: R9 X - ];
( K/ w9 `6 K' F
3 Y9 c7 Y! |' l. L/ o- public function __construct($config) {* C0 Y8 @, W2 g" m/ K- n$ d7 c
- $config = array_merge($this->defaultConfig, $config);
- V# X$ o3 [6 R - $mongoServer = "mongodb://";
$ p- V) N8 s) [; M2 z - if ($config['username']) {4 B& X2 {- s1 S' K1 o- f
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
# x6 [0 s! a$ k$ i - }: B6 N$ l2 p t
- $mongoServer .= $config['hostname']; [* Y: ?( r; x3 p* b
- if ($config['port']) {, p) O- _2 f" q1 V8 a/ L4 ]- p
- $mongoServer .= ':' . $config['port'];
9 |0 d. F4 h; T - }
6 a0 X, u, n- h - $mongoServer .= '/' . $config['database'];
( B: T- S3 P7 A2 W - % y9 Y% l: z; Z0 y2 F1 r8 G( @
- $this->mongodb = new Manager($mongoServer);8 {; P; b9 {3 ]. N& ?. b
- $this->database = $config['database'];
6 Z+ n* ?+ [2 {) N; y2 [( a - $this->collection = $config['collection'];8 z6 O( A4 y+ t
- $this->bulk = new BulkWrite();
; ]) Z% M2 v" G6 ] - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
T, V# f4 p7 s# o1 B0 E) J0 B- y - }
4 `$ B! d# m# w' m/ J5 K7 ~ - # u4 m; G3 c- O8 [/ N* d" e q: f
- public function query($where = [], $option = []) {
8 i+ C9 T# j4 }' H) S - $query = new Query($where, $option);
* W# ^' p; X3 E4 @8 k - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);) ~# t! d4 ]6 l6 D3 N) J! G
- 6 H9 `3 S& X7 F( Q0 F% e* G- S/ d
- return json_encode($result);
: B4 n# i( g( j5 C0 E - }4 t: O4 P/ n; A
( j; n8 g8 t, d( Y- public function count($where = []) {/ P. e& h/ K+ N2 ?# D5 f
- $command = new Command(['count' => $this->collection, 'query' => $where]);* r4 `2 n$ q4 }8 n( _& ^
- $result = $this->mongodb->executeCommand($this->database, $command);
' ?4 E- F) I' x0 V7 c0 U - $res = $result->toArray();4 y$ K0 {8 T Q: l- u) R
- $count = 0;
7 }2 m z8 l- s( O! n/ t( `/ k - if ($res) {1 M. d$ t, a: a$ ]$ J2 {0 G5 v4 ]
- $count = $res[0]->n;
) a; H$ ~( A. M3 ^ - }
9 z: I4 f6 V5 [
% I, f" E( q3 M6 e- return $count;
& H+ L, F% p, N5 e4 h7 T' F# [; } - }! P& L' Q- F7 N
- 1 D* k6 a' ~0 o# |8 q; P
- public function update($where = [], $update = [], $upsert = false) {- U$ |/ `% z5 I
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);5 r6 ?$ I4 H$ i1 c
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
0 E$ Z; D' b8 V' n- k$ h
4 P! m0 @& w: W$ n- return $result->getModifiedCount();
; ^7 g+ ~* J7 t3 ?) @8 J - } G/ @% g, x! K+ m* X9 \2 Z
- 2 D/ L# D) o8 U- T+ l! S9 ]; n. r
- public function insert($data = []) {
( W2 t( z" ~# A/ c$ x: h a W - $this->bulk->insert($data);/ h3 N7 T8 [+ r
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
4 F& ^' A. b" w. y+ X; a6 d
6 V0 T/ O- S: G0 U$ U7 @; F- return $result->getInsertedCount();$ v" c; e6 V* g% {& H3 u* D
- }
9 e0 H2 }9 E% C# Y( \* R - 4 }5 `, V! T+ Z: T( k3 X
- public function delete($where = [], $limit = 1) {
$ x/ b! @) o0 ~! }0 [+ o7 N; F - $this->bulk->delete($where, ['limit' => $limit]);
- ~1 `8 p, E0 D" r; Z; d o1 O+ N6 e ^ - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
9 E5 _3 a4 y I - & }: F: M# R& B0 [. b: S! ]
- return $result->getDeletedCount();
5 j0 c v t& S A - }2 p/ @& t) M3 p( N9 U. R
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原0 h% V/ ?5 r# f/ y2 V/ q
- 新
: z J. o* V0 e' `! h) F) a" A 2.新增- 原, I: t k, u7 \% j& G; `' L
- $collention->insert($array, $options);
复制代码- 新
E4 d, C! d+ \0 }( ^ r0 p/ v: [
- $resultOne = $collention->insertOne($array, $options);//单
% w5 W9 X7 ~- O - $lastId = $resultOne->getInsertedId();8 a6 p$ j, Q' y6 d5 b
- $resultMany = $collention->insertMany($array, $options);//多
` W$ u4 w/ g8 m7 x7 @ - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
1 n C0 \. N9 B; ?; r8 ~ - '$set' => $values
1 d& R% x/ |; p# L - ,[" x( r* O( I, ?& C% o8 N# m. w
- 'multiple' => true//多条,单条false4 A. L' B$ c) J2 ~
- ]);
复制代码- 新, q) o* N. {/ P6 {0 B* Y! @; U
- $collection->updateOne(
$ w4 [8 A' Q' q - ['state' => 'ny'],2 |! x3 k7 q4 B/ c8 m! f0 k
- ['$set' => ['country' => 'us']]: o p2 {& Y& b+ X8 [, ?5 }
- );) T8 N! @# A6 L9 h" h
- $updateResult = $collection->updateMany(- A' z! G% y1 C; J# t
- ['state' => 'ny'],) ~% K" F9 V) U3 K5 g; w
- ['$set' => ['country' => 'us']]
" h" |1 {/ U' k- o; G - );6 c) l ^, x2 }" J2 `2 T6 `
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原% o5 L( v" L+ ^2 }$ T* e# C6 t2 ?
- $cursor = $collection->find($condition, [
+ C8 m) x/ L3 V( j" e4 l - 'name' => true//指定字段
4 |3 A) J$ ^# |( q" v - ]);
% `! M: H# [( U6 O0 J - $cursor->skip(5);
% W0 p3 z9 B/ b. B* u7 q5 e g' j - $cursor->limit(5);8 u: F4 Y Y$ t3 R& S" f! l
- $cursor->sort([- K) a7 F! ^. g2 A1 f
- 'time' => -1) F& s" C- A9 @7 ?: |, J$ X* q
- ]);
复制代码- $cursor = $collection->find($condition, [
# o, J3 i5 U5 | U6 @9 h - 'skip' => 5,
& ^& r1 ]$ S- e" f" N5 C$ K# j# D - 'limit' => 5,
) U7 P3 `- D4 i6 j3 |/ S' T. V - 'sort' => [
; N: F! L4 N( g5 j" l - 'time' => -1
3 S, |0 O. {& D1 X - ],//排序
; H" r3 w& j; w t1 h5 i! q: L/ t - 'projection' => [
. G2 Z. G! y, K+ \8 r; N, ~. Z8 I - 'name' => 1//指定字段% }0 D9 c% L# [- S6 a* J) k/ R
- ]
' F4 B+ h O* f( w, Q4 { - ]);
复制代码 5.删除- 原
$ ] ^9 y1 m3 N7 |0 }% u9 A
- $collention->remove($condition, [
, n) H8 n& J) o/ O - 'justOne' => false//删单条7 X: h0 N& p! t. O, ]
- ]);. q& ?5 J& R- V
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
1 [/ K4 Z$ }# v% m - $collention->deleteMany($condition, $options);
- t" o; |) f T5 U; m# t! f
8 _- k5 d0 u/ S I2 [; G+ X. y- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([" S# g! u7 N5 C2 S$ Y {3 e% h, I
- '_id' => $tableName//我在自增表中用其它的表名作主键
; c8 T @" p0 N- j3 \1 Q3 _ - ], [
' A& \% C3 W( @$ e. T/ R6 l) v - '$inc' => ['id' => 1]//自增) G' `; a) }$ @( C. f7 c& o
- ], [
4 R* g* ^1 Z. Y4 d - '_id' => 0
% k. L" Z0 l; y( M/ \ - ], [
) h/ T" ~$ Y0 w/ F9 L! @ - 'new' => 1//返回修改后的结果,默认是修改前的( V6 ?: n m( h- ~! t9 \
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
. `& w) W' {, f) V% _+ j - '_id' => $tableName3 h3 l7 A/ J4 i; h5 O* S
- ], [. C" u( ]9 M, u. M3 q
- '$inc' => ['id' => 1]
# k- `2 w0 C8 z" n% }. `+ I - ], [& \# D3 C$ z& _8 ?' s) A
- 'projection' => ['id' => 1],# w& ~6 E2 r% @( |& I( e
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER: ]7 S5 X# K% a f$ j/ @
- ]);
复制代码 1 K# s' F J* @4 @' d
* ~; J, y5 m" n+ q: v5 Z; @ |