|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php9 V, U, \4 Q0 w* K
. j8 @9 P$ F6 `, R9 ~0 x- use MongoDB\Driver\Manager;3 ?3 {2 U# p, X/ G1 [( i# D
- use MongoDB\Driver\BulkWrite;( A6 i! N: R4 c! M X/ g
- use MongoDB\Driver\WriteConcern;
( F# d9 ` B; m1 {& p+ l - use MongoDB\Driver\Query;
" I9 ]7 ^/ ^6 D) s$ a - use MongoDB\Driver\Command;
7 M; R, H' W [$ M/ G - ^; Z4 T4 p7 A, J4 Y
- class MongoDb {0 P; J/ t# u$ R7 x
- p: `' J, _' h+ F$ V- protected $mongodb;9 Q! \1 J1 H* J0 {: ~7 z
- protected $database;
$ J+ K d9 K+ g6 q5 I; A& W, l - protected $collection;; D J2 A: R# e( ]( S, z9 C
- protected $bulk;
" t2 X3 N, X) K1 p+ x - protected $writeConcern;) |; i( Z5 D2 G8 S
- protected $defaultConfig
; C% G, a8 ], N( x' p4 _: i5 t - = [) s# `# A/ A" I* g1 S4 V
- 'hostname' => 'localhost'," V/ s1 Q! }5 r4 s+ v. i$ }
- 'port' => '27017',9 J3 y- q& e7 v! Q
- 'username' => '',
. O7 V3 u5 {) L0 ^- W" I1 C7 }% N - 'password' => '',8 D+ T1 ~+ \9 K, f) i$ C- a" l
- 'database' => 'test'
3 B' j. j0 R3 d% C( ~- T - ];: o& G$ h, y; j, y/ K0 Z3 }' V
- 0 ^% t( u! ?# Q# S; {5 e
- public function __construct($config) {
' Y. Z' m, T' a0 P8 ^) s: g7 j - $config = array_merge($this->defaultConfig, $config);
' I' U, d f h# _% d - $mongoServer = "mongodb://";; S/ m- |! C* \/ p* W# x
- if ($config['username']) {
2 Z# u6 H* e* u: A3 m: l - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';# `1 G9 i' k3 k; Q. m( Q
- }
% w, M$ j3 {. K" y u - $mongoServer .= $config['hostname'];6 U- d7 N3 z# `7 E* s- ?9 L7 v
- if ($config['port']) {' C/ B r) t$ f5 G4 C
- $mongoServer .= ':' . $config['port'];
' ^# \" }7 Y1 N1 T. V9 x - }
0 l1 j7 F9 j' D8 J$ M3 x - $mongoServer .= '/' . $config['database'];; w. v# P6 G8 D& H/ o
- - P, h$ U" a! f# A! q% W
- $this->mongodb = new Manager($mongoServer);
4 n" s. x% q; V - $this->database = $config['database'];9 X h9 H. x; X V5 a
- $this->collection = $config['collection'];" U" v, n, I) C. O5 [; y: L6 M
- $this->bulk = new BulkWrite();7 \7 S- q: _9 ~4 }& w
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
* U" ^; J6 _( Y9 K n - }8 n' @. W3 T" ^
0 e+ }, q# U6 P* k \& s- public function query($where = [], $option = []) {
7 o2 S- E5 f" [# F! w - $query = new Query($where, $option);9 N" m0 N( h# Y, j N2 |" ]( t
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);, w& w4 T3 H/ d9 ]3 o8 U' `: ^0 r
' f0 n6 @( I+ L: \: ^# ~2 t4 o2 U- return json_encode($result);
4 B0 h; ?; V( c/ ^ - }# A# X/ ~8 u* D3 w
4 M: s' C/ w4 K2 i0 i- public function count($where = []) {3 X7 Z. w! Q; m" z
- $command = new Command(['count' => $this->collection, 'query' => $where]);
+ `3 J' g* L% i8 D! O, y8 N0 v) c; x - $result = $this->mongodb->executeCommand($this->database, $command);
3 v- \) L, J, e - $res = $result->toArray();
+ e! O( r" o$ z2 C, Q; R4 f - $count = 0;$ k9 a7 B3 R6 u9 U: _2 `
- if ($res) {
* q1 J+ V6 l" n% l - $count = $res[0]->n;
7 ?8 ^3 |5 |$ j, P3 D - }2 V$ b/ |" f# {0 b. N6 N
4 M8 q1 e$ U1 _# F$ q* s5 N- return $count;) i7 w) B2 p" ~3 S6 k/ M2 b+ E
- }6 V, f5 b4 t# f$ A' f. h& d
8 A2 d7 l' Z. y1 g) i3 }+ c% _' G- public function update($where = [], $update = [], $upsert = false) {4 s- _2 d8 S$ ?5 L2 f: s+ o
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
, z3 D# e: P. _, u6 `0 G - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 U& @, H! F c6 {- b
/ [% W" ~ k- |5 }. C& p+ Q- return $result->getModifiedCount();
" _' s R1 \4 k* M# n; h) g - }& L7 H) Q( [ E
- % D: j2 t: w5 Z' l8 D4 G
- public function insert($data = []) {
" @- W9 a' s/ r+ X$ e* k5 P - $this->bulk->insert($data);
8 [4 Y0 {: a$ } - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);0 a! N9 |3 g% F- j
- / R- O8 r/ @" B. e
- return $result->getInsertedCount();
5 T1 ], W8 q1 o2 J0 N4 B - }, H+ t2 Y( Z Y1 Q7 ~
: m. t- t: I9 b [* v- public function delete($where = [], $limit = 1) {! P8 G) E% g* S; s0 j2 b
- $this->bulk->delete($where, ['limit' => $limit]);2 H! ?! o$ {% z8 ~
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);6 Q6 ^$ x6 T; M% f
7 V E% N6 o1 ]: H" d- return $result->getDeletedCount();
: W4 z+ C" U9 {& x - }: X2 ?* F6 e5 j1 M' A% m/ K4 l
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- 新7 }0 Q9 X( I3 [ K# B$ B# J1 r
- $resultOne = $collention->insertOne($array, $options);//单0 L8 u5 c/ ~1 [6 B( c
- $lastId = $resultOne->getInsertedId();
/ b. q8 k- d! C - $resultMany = $collention->insertMany($array, $options);//多. c* m; O" M, e3 o
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
5 w+ j5 c4 Q+ }- {/ |" m
- $collention->update($condition, [
% E$ q3 S9 T: Q, N5 R3 K - '$set' => $values$ V& E9 W1 q0 g' j- h& Q
- ,[
. F, i# h y" d7 v# s1 s - 'multiple' => true//多条,单条false; i+ j1 Q; S7 z+ _' m& s; I
- ]);
复制代码- $collection->updateOne(
: O$ S* r4 X8 } Y. c6 _ - ['state' => 'ny'],
/ T6 x, k3 f4 s) v$ z A - ['$set' => ['country' => 'us']]# N! t" h ^- H: _& C
- );
$ a+ ]6 B( h) ^. w) ~ - $updateResult = $collection->updateMany(7 @! ]+ y6 `' K4 q
- ['state' => 'ny'],
" o' o. @- F `. j7 D - ['$set' => ['country' => 'us']]3 y1 y- M, U6 j: \
- );
: p. w- @0 J2 l. R. W# t - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [8 d; o' `; n+ k4 e# z* T& d
- 'name' => true//指定字段8 m3 w( f! M7 d0 I4 R9 o
- ]);2 y6 J4 s& C8 c) n5 w" E% Q; u) J) @
- $cursor->skip(5);
6 M$ P2 \' D. P) G1 ^! r8 x - $cursor->limit(5);
Q1 Z: R! Z/ u7 l& u+ s - $cursor->sort([
0 J& o+ N7 y. N - 'time' => -14 \: G( J; `: E( I C! C
- ]);
复制代码- $cursor = $collection->find($condition, [
$ B' [- J1 ~7 \" I: g/ C; h) I - 'skip' => 5,
. \8 X9 Y# F! O6 y4 F9 Z- D) n - 'limit' => 5,
: w- x7 T: z* c" x: O: h' y2 Z - 'sort' => [ M9 j6 ?. L( ]. L+ @
- 'time' => -1
- T1 @- h6 {. c+ _) E. |) d - ],//排序1 o, T$ T0 s: q( u3 J
- 'projection' => [
r Q' u' l. u1 M( k8 b% `8 x - 'name' => 1//指定字段* ^" @) b8 I! L; ]4 u- U) i
- ]5 b7 ~+ ~, J& o; @
- ]);
复制代码 5.删除- $collention->remove($condition, [/ G, P# ^3 r5 k
- 'justOne' => false//删单条8 M8 M7 `' m3 J2 k% x
- ]);
, j. g6 s$ i, F - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
+ A9 S2 s+ Z! }# O3 \% t8 S, g. {2 F - $collention->deleteMany($condition, $options);' F$ e9 R( L( n4 w5 T
# ?1 G0 P7 e8 C/ B, O3 J" \- s; X- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([2 C4 U5 y b& T+ a- ?, `
- '_id' => $tableName//我在自增表中用其它的表名作主键) H. ?, u9 w4 _$ s. d
- ], [3 Q. ?; D) M8 c/ H5 @; \9 j! X& s
- '$inc' => ['id' => 1]//自增
]# S& @. s! @7 R1 ?3 L - ], [
* {3 o7 M! g# Z! T - '_id' => 0
8 J, `. V& @2 W. z: k5 F0 D- u. J - ], [
5 G/ D; N* m t5 M. I - 'new' => 1//返回修改后的结果,默认是修改前的
5 J: S2 H' Y1 J4 A - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
- O# `: k% X. z. d8 m* X1 j( n - '_id' => $tableName
+ ]% E2 _7 R. T4 a' a* a# ^, C0 k - ], [
3 b# g, N! i+ i. u - '$inc' => ['id' => 1]
! [% ?! E/ B. ?- B - ], [ S. R. X+ @5 I7 l6 Z
- 'projection' => ['id' => 1],; K! a' A2 ~* s O7 O& l
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
* _! S* J+ h0 ?3 l- d w - ]);
复制代码
% l; r, E$ S8 t, W, I
& k( E$ F) T; ?$ m, J* Y |