使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
! h, t% L Q, F4 L' g - 2 e: [1 C# m+ k
- use MongoDB\Driver\Manager;
# q0 ]4 E* c/ H0 H - use MongoDB\Driver\BulkWrite;
# w8 F; x( X- S, c% c z - use MongoDB\Driver\WriteConcern;
$ g" G! r1 M+ w$ Z( A) w0 W3 ^& C - use MongoDB\Driver\Query;
o* E3 x+ o; R& K - use MongoDB\Driver\Command;+ l4 n+ G7 c7 B: s, E2 l
- + y f/ }) t% p1 R3 C* q. F* S5 r
- class MongoDb {7 `! a! x# N4 e6 p( Q9 E9 d S
2 R9 e; g! _: V. O$ g8 Z' J- protected $mongodb;
5 T, i- R1 D( D - protected $database;
4 a& h4 L$ I6 |& N2 c& g - protected $collection;2 T4 V4 E" _" F3 F; O
- protected $bulk;
! M) Y' w6 i0 n& S" e0 I* i4 Q# c - protected $writeConcern;4 d0 j7 D$ U$ R4 ?: `
- protected $defaultConfig
" I& {) H* @" F Z - = [+ @1 r9 I! S" p- z* C+ U3 ~: O
- 'hostname' => 'localhost',. T" J$ O; G/ i) k8 r# A
- 'port' => '27017',
& ]8 Q+ M% p0 m! Z* s2 q - 'username' => '',$ G6 \3 y+ K" r, L- z* k) h
- 'password' => '',/ }# j1 o( O8 j; z5 P0 R+ `, z
- 'database' => 'test'
1 R' U u/ x9 e# S - ];
% L6 U2 R. c0 K& Z/ ^' o& o - . W4 F6 G7 n1 ^" U$ Z5 f
- public function __construct($config) {/ e% X0 G/ u4 k' e9 A ~
- $config = array_merge($this->defaultConfig, $config);9 R, _" p' y7 g
- $mongoServer = "mongodb://";
' r' i/ ~) w4 f$ P - if ($config['username']) {6 ~4 Z* R1 K$ e- t7 Z* l
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';. t% J4 j, V! J# i
- }; k* ]$ h- ?! V4 U' ^. }
- $mongoServer .= $config['hostname'];; x" U0 R s ^5 Q) f9 e
- if ($config['port']) {% u# F* x% B5 Y6 B2 O
- $mongoServer .= ':' . $config['port'];
, g$ l: d& x: v- U2 ? - }$ t3 `( k3 G( ?9 B j( Z4 L
- $mongoServer .= '/' . $config['database'];
+ |. N8 K3 j) _9 R) I I; t( P
; S1 y! N6 ]- f! Z; t9 p1 P# ~- $this->mongodb = new Manager($mongoServer);6 j( c( E. W4 z- C
- $this->database = $config['database'];
6 R* n. b8 C2 h* T - $this->collection = $config['collection'];- Y" D; \+ m; C, k* ]6 j) c- [; d
- $this->bulk = new BulkWrite();
/ m% n# J) v4 T" D& v - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);" @2 {: g1 U5 }6 H* e) o2 V
- }1 \2 _2 q3 _8 F; N9 P- j' Q2 I% a4 B
- / n: R$ u& u! z$ y6 w
- public function query($where = [], $option = []) {+ t' P* o3 F S/ s
- $query = new Query($where, $option);
. i1 K, E5 n3 f# K+ [6 X - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
+ W- N0 q! p6 E6 D
. ]+ x, I- c/ v% r F# G- return json_encode($result);8 F4 g, Y" n: m8 E$ }" d# ^
- }3 l& J0 z% Q2 g5 T$ s) M
. L* a U- Z" ]- public function count($where = []) {
2 B% H# D/ l' O5 I" w# H - $command = new Command(['count' => $this->collection, 'query' => $where]);& K: t O4 W; j# B' g
- $result = $this->mongodb->executeCommand($this->database, $command);
4 u9 J$ p& e4 t3 @! Y2 I) O - $res = $result->toArray();$ d1 ^9 K- W1 `; i+ ^% a
- $count = 0;
% ~ F$ u* s3 i' M: M% p - if ($res) {
3 B9 ~. t" @$ Y. L9 d - $count = $res[0]->n;
4 P2 [) t" w3 K - }
. U0 u* C8 M2 `( M) e) m" e' R4 n - g# T# b, _& y9 F
- return $count;6 }9 V" \9 Y' w! K: i
- }
( N! p3 }/ ]5 P0 a" I. J
: Y) S5 r, \2 b" D- public function update($where = [], $update = [], $upsert = false) {
/ [/ O0 h9 c, w( d q a8 Z& y, z - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);7 Z3 V* v+ F4 j8 B9 h% \1 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 J8 w) t8 p6 |3 u8 `
- ) [8 s, h6 m+ z) e) F3 `
- return $result->getModifiedCount();
, ^( ~* n. q2 Y. |. j$ K! O - }
/ R9 g- ~3 M. S8 _ - 0 N+ m. j4 _$ W- r& l
- public function insert($data = []) {
8 k& b) i1 q! y/ j( D/ ?" M) p( G; S - $this->bulk->insert($data);7 f/ ]6 G7 S, D' M* S( a) {$ ?# y
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);2 G$ Y+ _) O. e- ?. r% ]
2 T) v; J8 o5 S' N: f W4 d' p- return $result->getInsertedCount();' D9 ?! [# B0 h
- }
& `- x7 [) R) b" m, c2 s" q - $ l( V/ k1 F2 x# m6 T
- public function delete($where = [], $limit = 1) {& c# |" x A/ J
- $this->bulk->delete($where, ['limit' => $limit]);) y& n: C3 r$ ^+ ?1 a. A/ r
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
: `" P; N- M1 L
/ T, U, ]' |' T5 v2 n- return $result->getDeletedCount();
1 B% ?/ K* ]- c4 q - } E4 s0 p' U6 \, b0 Z
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新% z% V' N9 f3 e( ?8 J' }4 G1 T* s% U
2.新增- 原
# Q* P" I$ T) @! [6 [8 M$ T
- $collention->insert($array, $options);
复制代码- 新3 J( i! }4 u8 O$ Y6 T( T8 s B
- $resultOne = $collention->insertOne($array, $options);//单
. J! k0 e& `( V2 p w! A - $lastId = $resultOne->getInsertedId();
/ K8 Y& b4 x! A& L! j9 s - $resultMany = $collention->insertMany($array, $options);//多
( y" i* R' v- h - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原' L3 l% H8 U( d* e" o2 U
- $collention->update($condition, [
6 T6 u+ A) \3 U3 e - '$set' => $values& n+ }. d. C# h5 f
- ,[
3 ^8 C/ x7 R0 b4 ]! @1 T - 'multiple' => true//多条,单条false. V2 {. v' T( X1 |% T: B8 C
- ]);
复制代码- 新& k5 j$ }$ X8 a2 L& s( v
- $collection->updateOne(6 P, M4 Z! s6 D, q( n0 Q
- ['state' => 'ny'],( u$ l, W1 I* t; C% Y* g$ C
- ['$set' => ['country' => 'us']]# c' R7 W) B5 K- E F! J
- );7 ]7 x. a! `2 q" O1 c s
- $updateResult = $collection->updateMany(
7 E) {. w9 B, x7 ?& P9 g" f - ['state' => 'ny'],8 |' @. @6 t0 z5 F1 D% _+ a
- ['$set' => ['country' => 'us']]$ a/ z% |: N y( g3 N% w- I
- );
( _ N# P. z9 ] - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
6 X x' o. \ v2 Q% J - 'name' => true//指定字段' V0 J4 ]+ o; R& C$ e- t3 u5 D- k0 ~
- ]);
, ]- E7 C3 s* P6 t - $cursor->skip(5);
$ l- z! U5 I0 e8 a9 _' Y - $cursor->limit(5);
2 A, e+ X q& X- K - $cursor->sort([7 j3 N+ R0 i! V) h, k/ ^7 R( T8 g
- 'time' => -1
3 E. N- Y) c! k* s7 e - ]);
复制代码- $cursor = $collection->find($condition, [
7 E; g$ y3 S3 e2 P, W* }3 l. ` - 'skip' => 5,
U$ ^/ {% m" }; m - 'limit' => 5,1 ?% X/ K- `* |% P# L
- 'sort' => [1 ]5 ^ S4 l `4 q, V: {
- 'time' => -1
- j9 ]4 i5 H0 _$ \; I) k: R: y, F - ],//排序4 P2 L! C4 C: P* I& n
- 'projection' => [$ o9 b$ G0 Q# O0 {
- 'name' => 1//指定字段
# q' n2 g* Q# c/ ]3 a - ]
; L; i$ A) N' W0 s( r! Z1 F - ]);
复制代码 5.删除- $collention->remove($condition, [, G+ [7 P5 Y$ y) `: V' z
- 'justOne' => false//删单条' W) a2 Y3 p" r1 u- \5 L: t+ w
- ]);/ L- Q0 E$ v( d. l5 |# }1 m* a
- $collention->remove([]);//删所有
复制代码- 新
; R: n) O! z8 f7 W7 a& {" A3 j
- $result = $collention->deleteOne($condition, $options); U5 n- i+ [) W6 n& I) p
- $collention->deleteMany($condition, $options);
3 u0 f1 i/ i5 l. @* f7 @; v0 J, `
: S- |) R* E- t4 ?6 U- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
) I, L! D. Q" ^9 z. T! W - '_id' => $tableName//我在自增表中用其它的表名作主键% z" _. v8 W4 n' L
- ], [# w% ]: b4 P5 Y% x% g# q
- '$inc' => ['id' => 1]//自增
1 K: |) N f8 p* k9 c+ p - ], [) M3 u: X) [3 x7 B0 P+ y- K
- '_id' => 0
3 I o) ]/ {, e7 q) b4 d - ], [8 h& `+ F& i! K7 C# [
- 'new' => 1//返回修改后的结果,默认是修改前的0 ?4 P y$ V! {& ~
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([9 S6 a* i( h& j0 @
- '_id' => $tableName2 S& n) B* M% l8 l/ a3 Y
- ], [, T7 A* P6 G8 Q# D8 @' W
- '$inc' => ['id' => 1]. ~6 v. v+ U3 b/ y( l. y6 k
- ], [" s5 L9 U" g0 y- l9 B
- 'projection' => ['id' => 1],
) M7 R* B) H. j - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
?, u; p# t9 c: L/ h- } - ]);
复制代码 % Q: O9 `% G! q% g
, [1 l0 b9 f" [( d0 X, Q4 b
|