使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php: H) ]) e, H Z3 e0 M. ^
! X- r! O6 z& H9 K U, h/ k- use MongoDB\Driver\Manager;
+ t F" f( [0 Q9 f: H& U i) z - use MongoDB\Driver\BulkWrite;; {' W0 G2 H+ i: K: M& I2 S6 D
- use MongoDB\Driver\WriteConcern;) v* [1 y$ p9 Q3 ?# b+ T# o3 n
- use MongoDB\Driver\Query;+ E* H+ V% r1 N5 e5 d9 v# d- h
- use MongoDB\Driver\Command;
# `% r5 A: E) W9 s - ; g$ j; b+ a; f2 w' j
- class MongoDb {( I( r! T/ i; f% M. h: [
- 4 q" C$ x- k$ F' W
- protected $mongodb;
. w. }0 \6 u# O, _ - protected $database;, w, {3 I `8 ]& e% I
- protected $collection;
' a0 H/ p0 k4 z4 {9 r% n - protected $bulk;
" o* Y. ~% W* G# N$ ] - protected $writeConcern;1 u! M: r8 ^8 K* a1 @) K
- protected $defaultConfig/ O& s' U5 z0 z! z
- = [0 J% \, m% L" B( Y6 q1 N+ p2 i
- 'hostname' => 'localhost',) F1 X" D9 N5 T0 _( H; m7 K
- 'port' => '27017', Z' U: u% n- d, ~3 z# w- y' W
- 'username' => '',4 z, C! @: [- E9 u# T
- 'password' => '',
% \8 U- x2 R, N, e" p) F% A - 'database' => 'test'
1 r' f, L N h6 Z5 \ - ];
! s$ P5 e4 P) _3 M7 p2 B
2 ~8 D3 D: }5 S7 m1 v; k- public function __construct($config) {0 x3 T# E/ U2 @& ~( u' e
- $config = array_merge($this->defaultConfig, $config);
3 `% H6 A& B3 y* h* t - $mongoServer = "mongodb://";
$ K4 B2 J/ h; i, s0 p7 G - if ($config['username']) {0 Z6 H( l# X6 O& k
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';) y# t$ l# w4 _1 T
- }- T, E5 ^" H+ G9 z) W8 `5 B4 v
- $mongoServer .= $config['hostname'];
% w* L7 V2 W2 `: }9 m9 D+ | - if ($config['port']) {
{0 Y" H& ?: k5 X. k# K \. A6 y - $mongoServer .= ':' . $config['port'];; V$ I. t; m$ F' o% U) l% M. D
- }
" I1 l' h1 C7 ^, t2 S - $mongoServer .= '/' . $config['database'];6 |- Z( H% a" w+ z# u" z
# _/ x0 @ o! y* U) e& y- $this->mongodb = new Manager($mongoServer);
0 d4 j4 S( r& n - $this->database = $config['database'];) }! U! t* ^# Q& X7 l6 i3 h4 N! s
- $this->collection = $config['collection'];
8 O) l2 J- ?" C; O1 j- A - $this->bulk = new BulkWrite();: ]% b4 I! @* s6 q+ A
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
& p8 I% b9 A, q# T+ i% M - }
( \0 z. `! X0 c9 l: B7 r" R* N; I
+ U) B. h, w3 h- public function query($where = [], $option = []) { x" F B; `3 I- i
- $query = new Query($where, $option);" q; p, v" o/ v& h
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);+ X8 h2 O0 S$ p+ a# F
- - `# v. A) _% S& g- ~( k7 P( t$ j) Z
- return json_encode($result);0 p$ k& t0 R h; ^$ O
- }6 X- s4 o% A& Q1 _2 }8 \
- % {. g( F. H+ V' j* n
- public function count($where = []) {
$ L' T* {: i8 y0 D' Q - $command = new Command(['count' => $this->collection, 'query' => $where]);
7 ]3 n6 z. J# ] _2 L5 p" \ - $result = $this->mongodb->executeCommand($this->database, $command);$ N3 v2 Z/ n% A0 Y$ J
- $res = $result->toArray();
) e6 b$ Y; A' d. i - $count = 0;
# o' i$ R4 k' S2 G; T - if ($res) {: f- U* E. D, o+ q& N3 H
- $count = $res[0]->n;5 K H1 s: Z' u a
- }) Q" B$ `# d6 h* [; ~/ J) b
- ; c4 d% H5 a+ \7 t: h- _
- return $count;
. F1 }/ U6 B. \; D8 e( _ - }
# B1 J k: Q$ q! o$ t+ H& \ - / I5 G/ Q" X9 W: \' W- q/ R
- public function update($where = [], $update = [], $upsert = false) {
& i4 ?; O& b& F. C - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);5 J9 | s A8 b: P% y) ^# e
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
& W; b) k8 |& ^ D9 a' u1 n. c - 3 z' }+ i; _0 C/ c
- return $result->getModifiedCount();& C" O$ u) U* p' y8 y
- }" r+ @) R# |0 j* O
1 | i' m8 t, w/ ?/ M* a- public function insert($data = []) {
6 P! ~9 ]$ A$ x4 y- I1 F: W$ a - $this->bulk->insert($data);
9 S9 u" `7 O" U# D. D! { - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);; t: x' I4 b8 s9 J( D
9 J- Q1 k T! J7 Z% r# {+ P! H- return $result->getInsertedCount();
3 {: x: K% `. f7 A7 g- B* I( U - }- k/ S- H E2 Y( I+ e% D% n5 `6 _
- # ^/ L" C9 V" i" i1 {3 I
- public function delete($where = [], $limit = 1) {
2 k( [7 u1 j5 Z5 R2 |% f0 ~: L - $this->bulk->delete($where, ['limit' => $limit]);% j9 f& |! g" f1 T$ {( E; L
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);% l& A* _; Z0 t- H! {: Q
- ( [3 j- l3 Q# G( d+ b: Q
- return $result->getDeletedCount();4 ]6 v/ |/ a3 S9 o. Q0 i* }+ V0 v
- }
3 Q& c. M" s# w2 k! l" i - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原2 ^" W: j' A5 s$ n$ c$ E9 a1 U
- 新
* A5 C0 m5 T& {% g4 I0 q+ @) N6 z 2.新增- $collention->insert($array, $options);
复制代码- 新: K0 W* f* {. ?# i! s* ^- m
- $resultOne = $collention->insertOne($array, $options);//单5 p+ t6 T( n1 n; x9 e
- $lastId = $resultOne->getInsertedId();. s4 |% J* v: k- _
- $resultMany = $collention->insertMany($array, $options);//多
: \. T1 f6 ?( U' O9 T7 @ - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
+ a1 g" ?" E1 U4 \3 } m
- $collention->update($condition, [# v2 d! P; D7 u+ z
- '$set' => $values# c a8 _( C i/ ^ K
- ,[
. y" u+ ` D, l5 O9 t0 T - 'multiple' => true//多条,单条false
5 J9 a9 r8 X, ?3 {4 V - ]);
复制代码- $collection->updateOne(5 x: k6 U; C5 t+ X( x" [
- ['state' => 'ny'],, R8 V% q2 I& L3 c& Z% l; q
- ['$set' => ['country' => 'us']]8 P7 C1 I1 e4 [
- );
+ A5 C# g6 P, L7 g. n9 y/ W- p - $updateResult = $collection->updateMany( Y/ u3 y1 p& C) `: `& @1 ?: p
- ['state' => 'ny'],( X' A7 [. I3 y# c8 j
- ['$set' => ['country' => 'us']]
$ q% k- P/ g o; q/ ~7 o3 B ^ - );$ H0 F/ J u. g& h3 }4 c: E
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
! u9 y( Z @7 x8 B3 Z4 Q
- $cursor = $collection->find($condition, [
, _7 Z+ t) ~$ O8 p0 Y/ m - 'name' => true//指定字段
$ D: j( C9 X- E( _, W3 r( Y. \; b - ]);
. z) p$ k1 i2 c6 m8 n0 d - $cursor->skip(5);
1 q- Q! N# O2 E P M - $cursor->limit(5);8 b0 ^* P4 @' A# H- F
- $cursor->sort([
4 T2 U: C; B' V9 W& d - 'time' => -15 M1 u0 c- j6 j. O7 S# |3 c) i" h
- ]);
复制代码- $cursor = $collection->find($condition, [$ T( B1 P' c! \) |0 z' l$ g# b
- 'skip' => 5,! W' g4 I! H! L; ?4 \6 \/ w2 Z
- 'limit' => 5,
* `- S! {. Z; ?' D( }) F - 'sort' => [4 c8 k% _9 o8 M7 Y; u6 D. A
- 'time' => -1
% a9 c4 I' S, l+ O, i - ],//排序
! x% u0 u6 x |7 g - 'projection' => [
) {; q5 P8 I* { - 'name' => 1//指定字段3 Q4 b% y8 S/ n
- ]5 l- b0 Q- o5 Q9 N9 c
- ]);
复制代码 5.删除- 原
$ r- `; S9 z- K- n& ~- j) u
- $collention->remove($condition, [
5 K+ S3 \9 v: q; S3 _& U. }8 D; ^ - 'justOne' => false//删单条( o$ j+ O6 P- L$ S2 \0 E" m
- ]);5 k5 \, _, R$ E* [0 B: T7 c
- $collention->remove([]);//删所有
复制代码- 新2 }2 V2 Z5 s" o4 ]$ t0 f9 x
- $result = $collention->deleteOne($condition, $options);. t3 \ [# x2 D) H
- $collention->deleteMany($condition, $options);5 ]- z) O, n& M" ^& M2 ~
- 3 L; x/ I4 v4 z
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([8 g" B* ~$ e0 J, q1 V: i
- '_id' => $tableName//我在自增表中用其它的表名作主键
( `: n3 V$ @2 g! `: x0 h& B( b - ], [# b5 B2 L, a/ m4 `- Z6 [2 s) H
- '$inc' => ['id' => 1]//自增8 J/ h* \8 `. F, I5 ~
- ], [4 _; s% d! }. z6 j2 d0 k/ O2 C
- '_id' => 03 H3 R7 x U( R1 r$ \
- ], [
8 T9 }7 a f; s7 m4 b5 ]( q - 'new' => 1//返回修改后的结果,默认是修改前的! d5 o4 \1 Z+ \
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([& A _6 h/ V0 `3 N4 J2 \' a% _
- '_id' => $tableName
) ]0 r7 R2 D9 O" t1 P7 H" y - ], [
" n+ m2 f0 f! l/ v& h - '$inc' => ['id' => 1]
# Y: k$ d( p2 Y/ K7 |- a - ], [
$ m {& \3 n5 m- w0 E4 \ - 'projection' => ['id' => 1],3 f/ \' e. m( @/ D& e
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER0 P1 j5 U4 e4 \! E9 s
- ]);
复制代码 5 X% S9 R/ y9 L/ |6 J' B
; C/ `3 h$ ]1 k( ]# \
|