|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
& c) ]" x2 I$ i4 e
5 C. Q/ }- p+ a) \/ I' [- use MongoDB\Driver\Manager;
* B* O" K8 z& U1 j - use MongoDB\Driver\BulkWrite;
; R( O( w4 e* S - use MongoDB\Driver\WriteConcern;
: N+ _* l$ m* Q+ R, |3 ]( P - use MongoDB\Driver\Query;* h' y# {/ D3 K0 z6 S
- use MongoDB\Driver\Command;+ F. Q3 o e! a' y6 }
4 c6 H8 b# y: t. W; g- class MongoDb {
" r$ n* F$ C5 c1 ?' \% H - 1 j' K% K, S. S9 a4 ~( y
- protected $mongodb;
, }% ?% P9 H5 [1 p. V$ ?2 T2 ] - protected $database;
}7 Z Y$ ]6 c3 y3 h - protected $collection;
: o6 [# T/ h& n9 s - protected $bulk;) M5 _. @+ \. E4 S
- protected $writeConcern;3 e0 Q- c; c+ U3 x1 |" l
- protected $defaultConfig
4 G) H/ Y" Q8 n' G6 \$ C - = [' d1 S) r/ Q/ E% G3 r4 ^1 j! K4 A" ~
- 'hostname' => 'localhost',8 z5 O* S: t* } A; W& F0 d. {' K
- 'port' => '27017',
- ~- \$ C7 s$ {! _ - 'username' => '',
6 A4 u3 u+ J! [. }4 r; O - 'password' => '',
9 ~: B/ Z( R: f* K - 'database' => 'test'
/ D* h( f2 n6 F- m6 i+ u$ x0 n - ];
0 n# A2 o! R$ {$ {% d2 ^3 f - ( B, c) d( J- U2 w+ G$ }% D7 @
- public function __construct($config) {. R6 G. ~3 ]% F
- $config = array_merge($this->defaultConfig, $config);
, X/ w, ^1 }0 P& V - $mongoServer = "mongodb://";
7 I; u" N! p0 c - if ($config['username']) {
/ W1 T" C/ `7 i- {' e - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
8 ]" o1 e, _; L* P5 d - }: X% T/ _2 Q& A7 z
- $mongoServer .= $config['hostname'];
9 P A$ n$ P& c% O' \ - if ($config['port']) {2 G( o. r% d, d3 X* }
- $mongoServer .= ':' . $config['port'];
1 x1 S3 E: B" S- } R4 Q' H: s - }
3 P; K! _/ x- _& N - $mongoServer .= '/' . $config['database'];
8 f$ N5 l3 `# {
4 T7 p4 ^+ r* B! [7 S- $this->mongodb = new Manager($mongoServer);1 l* l, U" T. `9 y
- $this->database = $config['database'];; o. o% y5 P# Q) E
- $this->collection = $config['collection'];" Q5 r0 y5 Z. n6 ^& @. N" U& i
- $this->bulk = new BulkWrite();
; ^ \9 v% b: @' I( E - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
/ V6 ~# O4 Y" `8 n, k - }
: Q) }0 Q" O8 W2 c* G
* E, H* }1 }# T# o# f9 u7 c% S- public function query($where = [], $option = []) {
# k' z! C$ L* G9 `9 x% i - $query = new Query($where, $option);
) i/ H$ F1 ?" @2 h' T - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);" w0 u+ b. G" K- L7 [
" i! O% ?: `9 n$ V9 V- return json_encode($result);
; w: R [( }+ ^( m - }! O! E" U+ ~* i0 W, z
- / n8 c: p& v1 e5 [+ ? g% C
- public function count($where = []) {) }2 _5 Z' B* F& Y( o$ ?
- $command = new Command(['count' => $this->collection, 'query' => $where]);
U" C( A) r" M! A' b. r - $result = $this->mongodb->executeCommand($this->database, $command);
h% L7 e* ^5 a - $res = $result->toArray();
. P3 g6 m$ z3 E( E6 \ M - $count = 0;
- o+ l. M' Z* _. k - if ($res) {
* G) q; P3 W9 L: c - $count = $res[0]->n;* }' A# m# m( ]
- }! V6 `4 \' H$ V1 Y) `. f" G
- 5 o. N: m1 B% f
- return $count;
( u9 p, Q8 K$ \3 R2 Q( W( H! s8 k - }% R9 \5 p+ {2 _7 u, l3 Y3 k
6 f4 O! N3 H2 E5 \" Q1 M- public function update($where = [], $update = [], $upsert = false) {/ I: R4 T3 _7 p. N
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
* s s* s, @4 R* |: g# M# @ - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# @+ J* G( R5 y% h a/ a5 J
- $ X, m! o. v. W# s
- return $result->getModifiedCount();5 ~3 X* o* @7 W# k7 a/ n
- }9 t) K" m+ b. }+ y
- q+ P" Z: h8 O+ E4 r7 Z& V3 ~, r" M- public function insert($data = []) {) Z. O# K- N2 ~; L, `7 { T
- $this->bulk->insert($data);, _0 i7 {& ]' f* w# L' h% w
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);+ y9 U* A F$ l& O: Q) N
# k: \( F% n7 r0 C/ E0 a/ O" p1 D: p) {- return $result->getInsertedCount();
8 O4 h2 v9 `6 o( [# O - }& ], ~! L0 `0 d. P, [7 D" H2 e
; J1 \. @* b" v2 q2 \" g- public function delete($where = [], $limit = 1) {9 w4 m1 S7 R0 l8 n' a& I
- $this->bulk->delete($where, ['limit' => $limit]);* V2 V& W6 |3 M- Q7 E
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. P1 q/ \8 ^' z! u* c, R1 G9 @/ n# c
" Y7 N" S5 `1 ^5 e6 w5 c- return $result->getDeletedCount();
6 Q/ N3 C7 V0 q" E8 ` - }
" j% |' u; G+ Z( H - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
" z, j I. t7 B, m4 R1 z
- 新
, P5 F* [* l" U) a) G$ ]! p 2.新增- $collention->insert($array, $options);
复制代码- 新
( i9 o- e6 S1 C$ p, J" T) @
- $resultOne = $collention->insertOne($array, $options);//单
, A O3 A3 T* u9 a6 r0 W2 W4 \1 g - $lastId = $resultOne->getInsertedId();
9 U9 e. Q; u8 r$ [4 u) l9 F - $resultMany = $collention->insertMany($array, $options);//多
& w* K; _7 R0 Q" l1 Y - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [5 N" d) p) T! e/ O" y
- '$set' => $values
; V2 G; \8 O& F c% Z$ o y& o - ,[8 e; C# V9 s! n/ h: l
- 'multiple' => true//多条,单条false
& q# I" ~) m7 `) ^% ?2 } - ]);
复制代码- $collection->updateOne(
0 G' ?2 H. x2 Y$ X - ['state' => 'ny'],8 ` @6 b: K9 c \' P4 V
- ['$set' => ['country' => 'us']]& F2 T4 T4 S6 ^* i
- );6 E6 B/ _* A2 O/ K ` q5 x
- $updateResult = $collection->updateMany(0 ^0 R& G" @" @. o* M
- ['state' => 'ny'],% F( ?( f8 K" p: ^" R( x' Q5 d
- ['$set' => ['country' => 'us']]) z# d% z; C. x7 c6 L8 E
- );( r5 d0 D* ]+ U5 z0 K. d% n4 W5 O0 {
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [( i+ S6 m$ y* z; R
- 'name' => true//指定字段
. U+ z5 b- \7 ?& S+ l8 j - ]);
1 U1 I: Z+ ^ }0 D" e, t7 j - $cursor->skip(5);3 w* B2 A" \) Q* T. @0 J9 E% r- D
- $cursor->limit(5);! i/ a. U" m3 f9 t N7 U. c; s
- $cursor->sort([
5 x: M, _2 n7 i - 'time' => -1. m4 a% b5 I# j% J$ r1 {( R
- ]);
复制代码- $cursor = $collection->find($condition, [, d$ p) g( I$ v5 ^' n1 ~1 N
- 'skip' => 5,
; @2 q r, d4 y* s1 l S - 'limit' => 5," a, l5 g5 J+ S9 j+ z' D
- 'sort' => [2 A ?' I1 t) Z( }
- 'time' => -12 T$ K% k3 r2 S* q: l
- ],//排序. m9 b. x7 I; }( Y. U9 v* W
- 'projection' => [0 w* F3 N y7 G5 \
- 'name' => 1//指定字段; n ^ v: }% E5 L0 \; A
- ]+ k! c& H P, w9 p3 g
- ]);
复制代码 5.删除- 原4 F* ]4 }4 `& i" Z- [" I& W: b0 q0 I; Y
- $collention->remove($condition, [
$ @9 X* d4 x1 v( @% ^0 E# O$ R( a - 'justOne' => false//删单条* g! j; l6 {) }3 O! O0 a
- ]);
$ Q {2 ^* w1 B, \. U - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
, v* B( \1 Q& ~. F/ q' q - $collention->deleteMany($condition, $options);
) H. ^% C1 ` D: Z1 U( P) p, u- |* J
4 x+ z& R# x1 e- j4 k' J8 J- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
! _4 z+ Q1 \/ c- c - '_id' => $tableName//我在自增表中用其它的表名作主键
3 w8 r1 R; A, a2 L - ], [- j2 F0 t7 w6 \' e" j, l9 O
- '$inc' => ['id' => 1]//自增
" }) D+ r* q5 }4 b% Q w. h8 u - ], [
2 t9 L5 k/ H& {6 p: q - '_id' => 0
$ `- D; W( \$ }- E8 i' U7 D9 B$ k - ], [
8 F) F6 S+ e4 e+ s" V - 'new' => 1//返回修改后的结果,默认是修改前的
3 b) o8 W7 Y) h9 Z% i - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([* [0 m% `2 T/ ]. Y' [# C ^9 f
- '_id' => $tableName
, {) [4 H, R- u - ], [
; a9 Y n/ W3 c4 d - '$inc' => ['id' => 1]
# q6 }" j7 f0 ^ - ], [/ Z1 \7 b& Q- q$ T; U2 s$ J/ u6 k
- 'projection' => ['id' => 1],
5 G# R* Y- o# i - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER' |" ]' S2 G8 D& S/ \
- ]);
复制代码 ; O0 ~$ D. ?. B1 v9 |& U
4 S( D8 K5 Y$ r |