|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php& k8 N6 h3 u; o, h# ^
- ' q0 r' S# u. n7 v* H- K/ E( Y
- use MongoDB\Driver\Manager;
2 a- a# w/ n' b( \$ c+ P - use MongoDB\Driver\BulkWrite;4 K& q- k9 [; Y4 R
- use MongoDB\Driver\WriteConcern;
5 S8 F: u8 o8 M& Z2 g0 _ - use MongoDB\Driver\Query;2 N7 i1 B1 v2 L: O3 ~- k5 p
- use MongoDB\Driver\Command;
+ i! H( b5 ?: ` - 0 e- m- o+ \ Q4 b* Q. x' f# s# a
- class MongoDb {+ S0 Q. _; G3 V: l c
+ D- E1 D, z' V- protected $mongodb;2 O- ^) k2 A. }) n+ {
- protected $database;. t1 A0 ^0 w! ]( N8 ?! P2 z! P' M
- protected $collection;3 A! N) r. N, z3 b# G
- protected $bulk;
! `# i/ [: |! ^+ b/ e. ?2 t - protected $writeConcern;
0 P+ i* t; w, w6 y- L- |6 w7 f - protected $defaultConfig
% @! A5 Q& z# B& ]6 ? - = [& i. m) u) z3 K" G: {7 r8 `! Y
- 'hostname' => 'localhost',0 O! [, t% g4 ^# t" M, u
- 'port' => '27017',5 x$ b8 \- H @) v9 A
- 'username' => '',
; `. B# K, q5 t - 'password' => '',2 x6 J" F* C: n9 Y/ I0 P; j
- 'database' => 'test'
3 K" g5 K2 D' J6 Q# @ - ];
0 r1 ?; }" h: [
0 b1 z* }8 ^( z) E7 O- public function __construct($config) {
; x+ }7 E- s( ^ - $config = array_merge($this->defaultConfig, $config); j8 m' F: u! [+ [; Y1 F# ]2 X/ ~5 i
- $mongoServer = "mongodb://";( r1 y# p. D4 l! [* E
- if ($config['username']) {
5 n& N$ |/ ]* Y& _( \) N - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
" D7 r& J8 o# p" r: @( D - }3 M! y- n$ x0 P* q
- $mongoServer .= $config['hostname'];0 p7 W( M8 S3 V9 d
- if ($config['port']) {
: ?4 s6 i3 ]" i4 H4 j/ }% F Z, u - $mongoServer .= ':' . $config['port'];
- y1 K& T" P/ E" X6 v - }
5 U; A" E; I% k3 x# F/ u - $mongoServer .= '/' . $config['database'];3 _0 ?# i) ?) y) E. `9 o7 `1 C7 _4 s. `
% d ?2 y3 v1 Y* T- $this->mongodb = new Manager($mongoServer);; l0 A/ o( _7 W9 J9 ~9 _& E/ V7 }0 p$ t- G
- $this->database = $config['database'];
+ Z5 s4 Q" O' p* _ - $this->collection = $config['collection'];6 f1 ~# d2 u4 R0 |+ i
- $this->bulk = new BulkWrite();
6 Z. x+ Z, J( O I- R4 I - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
* R1 m* i* X/ A - }
' i( D6 _3 @7 P' n; g2 m3 G
, F$ [1 F5 ^1 X& t% g) b- public function query($where = [], $option = []) {
7 t+ W" b+ S# o - $query = new Query($where, $option);
! |" E, t# f% P - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);6 y+ \1 G; E' _6 I: g( n; c' g
- 0 s, Y$ ?& K+ g" c
- return json_encode($result);
( N: Q, ?; f2 ?+ ~ - }0 ~2 U( J& U r: @; X# b
4 I- N- l0 z- _- public function count($where = []) {3 v8 N: J; {: ?: _: D6 Y
- $command = new Command(['count' => $this->collection, 'query' => $where]); v9 W% z, D6 H. k2 T
- $result = $this->mongodb->executeCommand($this->database, $command);
}# Z4 }/ G( B# O6 h - $res = $result->toArray();
: ]# v1 Y% N1 @; s) _ - $count = 0;
+ [+ K( y" U0 S; J2 W8 G - if ($res) {
7 x/ G# o* x4 T" b j! | - $count = $res[0]->n;/ T; m, X, i: h1 r \6 y4 R* h
- }
s* N' O$ u/ Q' T+ H! I6 S0 {
8 C$ \! }7 E1 ]" B1 C$ q, d- return $count;' d" R1 X' d) m& I9 R2 l! D
- }% H6 f" f" H( Y6 S, X
- $ R. k8 A' M2 e& `7 Z2 F, x0 [% }
- public function update($where = [], $update = [], $upsert = false) {9 F1 ]5 } q" z# x7 L: r+ D& o) o9 i
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);# z; W0 L+ Z* ? P) _* Z9 `
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);5 W$ x1 J0 h8 v/ Z# }
- % v d3 [; Z. ?0 J( B6 M
- return $result->getModifiedCount();. i8 t6 ]" z9 j! Z' T5 Z
- }* `. R2 m& I' j9 ]5 w$ V
4 E# C9 Y ?* p( _- public function insert($data = []) {
; i i. u! D( f3 ]5 j# X - $this->bulk->insert($data);
8 ^! k. m! d$ Q9 B* t% S" |. I - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
" {( Y% x2 j. ]
# G& ]& f" U) x$ w- return $result->getInsertedCount();7 \* W X8 v# D) T/ m. I4 N m
- }
1 [" R5 q5 d6 ]! `, a, D
5 Y. O* v$ {$ m6 @( O) M- public function delete($where = [], $limit = 1) {5 V a' A; v( w9 w% ~
- $this->bulk->delete($where, ['limit' => $limit]);* a# e8 K2 l. Z; s9 C$ }
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
+ v8 u- U/ h Y( X7 ]
1 J" q/ @, `* N# N9 f- return $result->getDeletedCount();
" r, b& t# f' [; J" U; ~- f, ? - }
; f. @% r- y# p( n - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
/ f" \9 N7 G5 d, N3 b1 \ }! ^7 `7 y
- 新% n: h$ J2 Q! t0 \6 e' z- o; L
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单1 [6 P$ N: @8 L2 g2 Y5 o; x3 U
- $lastId = $resultOne->getInsertedId();4 c: S( N! ]7 ]7 S7 d
- $resultMany = $collention->insertMany($array, $options);//多
* k) g1 L" d! I2 m( `. h. Y6 z - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
' u# H7 v2 A* m2 q u% J9 A - '$set' => $values
2 f c8 y% k4 [& w! w5 B - ,[, J& k. R, T1 x1 U1 Z
- 'multiple' => true//多条,单条false# O# ?4 i) C# D& T8 a q9 [# w4 C
- ]);
复制代码- 新' a: B# o) k V% S% z1 L. E7 L
- $collection->updateOne(
8 Z! m1 m+ U; h3 w/ j( j - ['state' => 'ny'],
/ V! K0 a: _. ~5 I1 B - ['$set' => ['country' => 'us']]) v% e2 s# g% B% D
- );9 ?& b- @1 L9 j5 S! ~2 B
- $updateResult = $collection->updateMany(
7 s0 T9 i1 O3 f' f* k5 Q( d - ['state' => 'ny'],
# W1 Q) [! l- i6 S/ N8 s - ['$set' => ['country' => 'us']]
' i6 F: G$ H% k) V0 H - );% \* T; c+ g+ w. f' t7 n- w! |" N
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
* `( n* {# r, `, r8 H) h - 'name' => true//指定字段
8 f( o1 t: l, M0 o/ P - ]);7 _3 s1 A, n0 J3 {+ E
- $cursor->skip(5);2 W7 V2 ?" B; `. u
- $cursor->limit(5);
* d, L# i8 M. r1 V6 z - $cursor->sort([
$ F+ C' {& Q) m# w. S - 'time' => -1' \* d$ |& u( T) r9 v# x
- ]);
复制代码- $cursor = $collection->find($condition, [6 S+ s3 K6 H* V9 d
- 'skip' => 5,# Y1 h/ B7 k' [. u3 P6 ^6 J; I! u
- 'limit' => 5,
* j: c% B* f$ u+ U - 'sort' => [, L/ X/ W5 b |# U9 F4 M
- 'time' => -1
! g' k5 `7 j5 n, A) y% R - ],//排序
1 i/ e% _9 |5 n. t* g - 'projection' => [
4 P$ X3 f% O$ t/ t, D - 'name' => 1//指定字段
+ H: T9 a1 W8 p - ]
! Y5 `, P8 r3 ^, ?$ S; V - ]);
复制代码 5.删除- $collention->remove($condition, [
. E( m; P+ L! D5 K# t Y! r - 'justOne' => false//删单条
+ Y" R7 j; H. L) Q8 ]* y3 o - ]);
2 Q# k0 Z0 o* C7 C8 v9 E - $collention->remove([]);//删所有
复制代码- 新
4 r! J r5 K% ^6 E h) A+ ^, K; y
- $result = $collention->deleteOne($condition, $options);
6 p! h) x+ ~5 @6 ~$ ` - $collention->deleteMany($condition, $options);
0 N) I! J4 G4 j1 G; Z$ }6 F3 u; e0 r) T - 0 f1 D! D' d, j
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([ i% X5 c+ R! I2 E* P% u5 D
- '_id' => $tableName//我在自增表中用其它的表名作主键
$ z, |' w8 I4 h$ E- p7 z - ], [
6 g% U! f! o& F1 U1 R4 n - '$inc' => ['id' => 1]//自增
" u8 a( _# r# O - ], [
, E3 K: w+ B$ h( m# Z# E! n j3 }% | - '_id' => 0% y6 `" d* [5 p- H' O1 M. c
- ], [" d, T1 _/ {. I* S' {! Y
- 'new' => 1//返回修改后的结果,默认是修改前的
6 _* H; u s! |( Y - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
, u2 \! e, C( L N - '_id' => $tableName/ f/ t' A7 T/ I2 O4 a
- ], [
: N: b0 @ [- N" r/ I - '$inc' => ['id' => 1]: B# T- g5 u9 n# p4 M% I& P
- ], [
5 W9 d+ v; D. t/ b: O* Y - 'projection' => ['id' => 1],
& F, f" E+ K; C; Q% K - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
2 y2 H# k8 @4 X' D; b( Y+ o - ]);
复制代码 % h! n! x) t" N1 @! @ E: Q
. a' k& \* z: |4 B/ ~( Z |