|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
1 [7 ~+ Y1 j% ]& O! ^! p. ~* G$ T2 d" h - " ~$ G; u' m. e) N8 w( ^
- use MongoDB\Driver\Manager;
4 H( \$ O4 h4 s1 {7 T* M - use MongoDB\Driver\BulkWrite;
6 w. z1 a: I% t& I1 p9 k& q - use MongoDB\Driver\WriteConcern;0 E$ I! C; }. J, R5 p2 o/ L6 S
- use MongoDB\Driver\Query;
, G9 D: M0 X1 J0 G9 q" n5 b- x - use MongoDB\Driver\Command;
9 ~4 C8 m( U/ z
' C* D9 N3 Y/ S& P; g/ }; k- class MongoDb {4 _- S; B" M% V$ u) T! j0 k
- 8 ^. r7 h" ~' V
- protected $mongodb;
- F6 n- ?! D! p. ?) ?0 J& m0 s1 y - protected $database;+ i1 q+ x9 O2 P) u: j$ e! f
- protected $collection;
; H( {+ c6 |+ |$ q/ y9 q/ I - protected $bulk;
- Q' f- D7 |- G. o4 ], F - protected $writeConcern;
0 n9 L; W9 S$ |8 s5 X - protected $defaultConfig) o& e6 H5 N. P
- = [
" t: W5 f" [4 T6 ^ - 'hostname' => 'localhost',
q5 k# j- s: Q$ A1 W - 'port' => '27017',
' W- m, g+ n) I: p - 'username' => '',
9 o1 S- G# ~4 I4 _8 r - 'password' => '',
; S* ]" V4 p5 M0 P7 A( [( I0 X0 P - 'database' => 'test'
; M& q! e0 {& z6 g0 ~ - ];
( g% F3 n. M( H' Q
& l5 C. l: _9 m- public function __construct($config) {( j. q1 ?6 ]" b, Z" t% Q7 C
- $config = array_merge($this->defaultConfig, $config);
" Y# @# ]- v6 x0 B3 G - $mongoServer = "mongodb://";
* e T0 g' ]1 }" J0 G/ g1 N% | - if ($config['username']) {
/ a/ Y0 M' Z" n& e- I2 A - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
/ @, ~- K/ M' \& X1 J - }
6 }& C3 |/ b5 ? - $mongoServer .= $config['hostname'];0 w2 z9 ?$ T; v* m* r7 A! K3 G# W
- if ($config['port']) {! [/ M- \9 ?% V. s* i
- $mongoServer .= ':' . $config['port'];
; _, \( e. r. a4 a3 @ - }
& R% {; W8 P$ L: p a) B! M/ E - $mongoServer .= '/' . $config['database'];
/ x' \; ^ y/ s2 c- F5 ^; h: U. l/ ~ y - " \% W% {2 a* @
- $this->mongodb = new Manager($mongoServer);+ v, e% r3 ?7 z8 a9 W
- $this->database = $config['database'];
. B6 E2 ^/ [* d+ u! [ - $this->collection = $config['collection'];# ^: m' b0 u3 z, G
- $this->bulk = new BulkWrite();
% l7 z+ f0 D! m. N& Z1 e! c - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
! g; d" v b6 O C0 o - }7 T8 V, P' d! [4 Q" A, x$ V' j6 A; A
& ]; Y; c" B3 G7 \- public function query($where = [], $option = []) {
" ?7 {0 n- G" F- z0 G% W! D, Z. Y) ? - $query = new Query($where, $option);
" b1 L M1 l/ N% }' P - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
6 J( W. u8 m% ~+ H; B8 w
6 c& }5 E) X! A9 ^- return json_encode($result); e `0 g, t. h/ W
- }
2 w7 d+ j) E/ _ - + F- _9 B: ?- u3 I6 y. Y, u
- public function count($where = []) {
% K& B+ s0 ]/ e8 p - $command = new Command(['count' => $this->collection, 'query' => $where]);
( ?# m: i4 J" Q# C - $result = $this->mongodb->executeCommand($this->database, $command);
& t/ x! e: a( I+ [ - $res = $result->toArray();
2 x7 r. U# W+ W - $count = 0;( V" e2 Y1 S6 U
- if ($res) {' o) F* |+ X6 c' c0 Z+ B- Q
- $count = $res[0]->n;
* C0 D+ G5 }! a; f1 X; Z6 s - }
- j. c& ]# o5 e: Y - : |' C( u, M/ G/ r8 Y9 S' @, t
- return $count;
1 |& @: [$ E. X7 f% z9 r% u - }. {; P' D2 A3 W! b9 D3 c
0 G8 x1 H. J' c& P- public function update($where = [], $update = [], $upsert = false) {- y" [0 s5 e2 @0 f
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);, d' u2 c, q v
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
% z- q: Y; W( a4 B% J
; i, f% s+ e9 \) m* Y+ _- return $result->getModifiedCount();
( [6 M. r( N- e+ x% E$ ~/ J; b - }
3 U# A) E5 f+ m- \: \0 {" i0 x) M - 2 T4 @) Z/ P1 r* f# e+ `
- public function insert($data = []) {
! Q7 B9 g, w; q$ v* c7 B' K - $this->bulk->insert($data);0 O4 K2 L" ]/ _# r' J- A
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! p& z3 @, M0 }6 l" N! l# v1 ~$ u
- 8 M6 [) a. |% ^+ C* j$ @
- return $result->getInsertedCount();+ a {6 q, D5 {7 w- |
- }
9 R2 \; @0 A n6 s
/ M. O2 [8 X7 V4 |; L6 s4 b- public function delete($where = [], $limit = 1) {; `8 }1 q% Y) W3 Y6 W6 s7 Y
- $this->bulk->delete($where, ['limit' => $limit]);
. u1 G9 U! b0 L R4 O - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);0 Y5 x; l' M$ h) p+ G3 Y
: a) r/ `9 t0 J1 F- return $result->getDeletedCount();. G% ]% S9 ~' {% f& f
- }; U, H) p( M# f
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原8 h3 X. z; u, ]% I. Q: @. \* l
2.新增- $collention->insert($array, $options);
复制代码- 新
" w0 `- G/ w1 Q( Q' T. @) A+ h
- $resultOne = $collention->insertOne($array, $options);//单
+ u$ g" {# k" n! @( @, W$ y - $lastId = $resultOne->getInsertedId();
! Z9 v2 K# z% U1 u0 |# m - $resultMany = $collention->insertMany($array, $options);//多. l+ x) z! k" U' {, {# g4 n
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原. d" L: x* [# \( Y% y$ B2 I+ ?
- $collention->update($condition, [* `4 e9 ? B- S4 ^/ w; O6 H0 k8 w
- '$set' => $values
" k& E6 x- p/ X6 H4 @5 i2 D - ,[
) K" P( g- q) f2 C - 'multiple' => true//多条,单条false0 W+ N3 l( a7 e
- ]);
复制代码- 新! @; G n- ^9 `7 P7 j; i& @# J
- $collection->updateOne() X( g, N0 s: Q
- ['state' => 'ny'],+ }9 C+ J1 s- W8 l% V, ~" g8 `2 \
- ['$set' => ['country' => 'us']]
9 l' b5 [3 n$ j0 Z& Q - );
/ Y( H7 a, ^) S% T7 J' t - $updateResult = $collection->updateMany(; H8 l8 Y+ J8 K6 M
- ['state' => 'ny'],0 x T6 i/ u0 d6 t$ T
- ['$set' => ['country' => 'us']]7 L. v5 {) l! H; @
- );" L% j, } U5 h0 m. `
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
! C, |: R7 w2 Q7 G. J$ Q
- $cursor = $collection->find($condition, [5 ?9 n, T ?& F4 G( e4 @2 w
- 'name' => true//指定字段
H, a& p' s) P% K3 }4 y - ]);0 [- ~) ]' q5 A2 m* m3 q6 s
- $cursor->skip(5);# O6 I; p* O* f8 M9 L# g
- $cursor->limit(5);6 J( Q! w& C6 `# s! T
- $cursor->sort([. u: m6 d+ o& _
- 'time' => -1
$ K& W l, ^) {2 w+ U! k - ]);
复制代码- 新4 R! S! h8 U: L# o2 O; H
- $cursor = $collection->find($condition, [
: i7 N) ~& K! c+ r1 Q6 B - 'skip' => 5,
; P* Q: q, n! W2 J# c' e: G - 'limit' => 5,! P; C9 T. o) I- F; u0 c3 I
- 'sort' => [, L, l& v5 x6 r( J, u7 Y
- 'time' => -1
# ~6 C& Z6 s/ s7 S - ],//排序, z1 z' h5 g& v, |9 U8 f4 O
- 'projection' => [
$ `" }0 [: m1 S. P. \6 g, f8 O - 'name' => 1//指定字段6 n, T5 x2 |; ^+ u5 s/ E9 L
- ]
& A* Y4 ~8 ^0 s# \ - ]);
复制代码 5.删除- $collention->remove($condition, [ \3 b( x) ]6 `) M# |
- 'justOne' => false//删单条
: M6 k! E, [' v( D. v# I+ N( c: k - ]);- b* T3 c. N! ^3 X0 a7 }, q9 M
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);( Y$ `9 }# ] ^ J, i7 X
- $collention->deleteMany($condition, $options);1 Q I+ i3 X* x! G8 e% A
- 7 Q; O1 S1 g, H1 T* R5 c2 \
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([1 H& s+ V( u; A6 T+ i$ p
- '_id' => $tableName//我在自增表中用其它的表名作主键
, N: I1 k c# O% X% A B- \ - ], [
1 Y. B. q6 f' \& L( A( s* I - '$inc' => ['id' => 1]//自增
9 d( A# J( c+ J' I - ], [
& ~( U# [& ]7 {5 x( k - '_id' => 0
8 P* A& _! u; g! R& `" C - ], [) T K; n- n' f) e3 r8 y8 M
- 'new' => 1//返回修改后的结果,默认是修改前的( d4 F) @( R: A) b) y' H
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([- Q6 i( Z1 q' U4 ^7 c# J' c- w
- '_id' => $tableName# r" N1 x& ^9 x" s
- ], [6 V# {& |# g) O2 F1 c
- '$inc' => ['id' => 1]
: c1 ^) j& o' Y9 ]8 ^2 ] - ], [7 I8 r6 Y8 [1 l8 I
- 'projection' => ['id' => 1],
% M+ a% \: h2 \7 }3 j7 p" } - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
! c3 ?8 H m* `( \ - ]);
复制代码 ! ?. ~; Y* `" {
$ k& q, o2 n/ \8 N$ T |