|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
3 n% g1 o. G. f' G; P1 z8 Y - $ k. u7 k4 b. f( u; Z
- use MongoDB\Driver\Manager;
. b2 x# ^- `: }1 y' b7 l! [! }$ p - use MongoDB\Driver\BulkWrite;$ o% v) G. T; f7 w2 |
- use MongoDB\Driver\WriteConcern;: A8 t$ a. Y. ~3 M3 g8 } j% ^9 P* J9 \
- use MongoDB\Driver\Query;
0 ^3 D, X2 H% c/ ~2 ? - use MongoDB\Driver\Command;! T" E& X) X" X
- ! N& O& N' W2 x. p3 ?( i
- class MongoDb {
5 [6 g3 b& F' f' @, `* m5 u' J - $ w3 `+ r' U7 |0 r0 U" G) |
- protected $mongodb;
9 R3 z$ y2 r# Y - protected $database;! |3 w& j! X6 l
- protected $collection;
6 |0 c) H" ?: r- w) U2 | - protected $bulk;
2 U* g; S/ H0 X0 H - protected $writeConcern;+ ^" f& }6 }; { ?" @
- protected $defaultConfig( R4 A3 r* K5 T
- = [
/ F$ n" e! U, D - 'hostname' => 'localhost',
' E) J7 Y2 P. i0 f& c- P - 'port' => '27017',
- s0 _4 t- B' G - 'username' => '',
$ ?: @ g8 R5 _8 z9 r9 W! D - 'password' => '',5 M' q0 J4 K; ^) u3 m
- 'database' => 'test'6 z. J' v* p- @3 D: t2 u$ m% C
- ];& H$ t% ?6 f. @1 s- ~5 D4 ~
- 6 G# \* H: v: B
- public function __construct($config) {7 X; ~# R z: d" A
- $config = array_merge($this->defaultConfig, $config);
/ L2 X& P1 m$ U% q+ o$ ^ - $mongoServer = "mongodb://";" i/ ~8 L) q% f; J' ~( q( y) q6 ]
- if ($config['username']) {- B& U; }9 J8 }* j) M8 h
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';% ^4 Q# \# O: E" K" \) n: J
- }8 H- _9 ?0 t# u' d
- $mongoServer .= $config['hostname'];$ F4 U- \' o, Y: M
- if ($config['port']) {
" |; u* O& {3 e! j- A+ }1 |; f - $mongoServer .= ':' . $config['port'];; K `8 n0 q+ n+ H+ {
- }, |: D3 N: O# M; k6 n a
- $mongoServer .= '/' . $config['database'];
* P% l5 D2 i" t: U" P; H
0 k9 K& ]- ^, a0 j- L+ B* a- $this->mongodb = new Manager($mongoServer);7 b% [7 K; L2 E; ]
- $this->database = $config['database'];; s. a& {; j; h. n: y. ?( G; ~2 X( L
- $this->collection = $config['collection'];5 O0 P( U( m) p; ^: C
- $this->bulk = new BulkWrite();
# k- Q I8 I" B - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
$ N0 S5 L+ M) R# M - }
* E0 n. g: z. N' } - 0 {5 z/ v q- u( P
- public function query($where = [], $option = []) {0 x9 S3 v( f2 m. b* G
- $query = new Query($where, $option);
9 y; h1 G7 K& R - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
4 R1 W; B0 D0 X. ] - 0 v) {( t8 R; w/ r: N
- return json_encode($result);7 q' u+ y0 K1 d* L0 y3 k# A( C( w
- }
- ]# s1 X& V9 c
3 y$ f- E, o4 [9 B$ k3 Q; h- public function count($where = []) {1 Y" U9 ]" N4 T. `& G4 C* G
- $command = new Command(['count' => $this->collection, 'query' => $where]);6 c x9 X! H# V
- $result = $this->mongodb->executeCommand($this->database, $command);' l5 w$ |9 F/ S. H! G9 Y
- $res = $result->toArray();
& q. @! ?: d. @- E5 p5 S - $count = 0;
7 `9 Z. c0 x, x; C% I( B - if ($res) {
- E5 n8 b6 U8 M( s - $count = $res[0]->n;9 l% z: D0 y0 a$ ]5 y7 q- Y8 v
- }# v, ]4 ]; ^% V: [6 ~; F
- , v% Q4 B/ D4 Y( X8 q
- return $count;
2 C9 ~; _( E9 I- q - }5 b3 p8 r. ~6 I6 y% X9 |
- ( J& A# O; s+ M! z) i, t
- public function update($where = [], $update = [], $upsert = false) {, v; \" r0 S2 c/ t% l1 R
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
8 p: f) D. F1 W6 w$ y6 t+ m - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
8 @+ z: h" M6 u+ s2 x - }7 H3 Q0 c7 x/ f v
- return $result->getModifiedCount();& L5 Y4 @6 q2 b, C
- }* C3 U) T6 Q$ v, N+ ^+ c7 _/ y
- 3 \0 F& ^, P8 u
- public function insert($data = []) {* R) h" j3 S7 L
- $this->bulk->insert($data);2 ?0 e" z" R( x& w0 X- F
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);% v* u& w' O# [7 a) i
3 x- u X; F* T" D4 n' W- return $result->getInsertedCount();( O# u9 v) _! k
- }& |' X- F4 W- U: @; Q& I
/ h% Y7 X- t% X3 k4 v# _- public function delete($where = [], $limit = 1) {) |( r% R" r; t. E. @2 j) X6 L
- $this->bulk->delete($where, ['limit' => $limit]);/ n+ c' \% J, k
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern); x2 P1 K1 v" G7 M; i
- # y/ h x) A& A9 |* \/ g
- return $result->getDeletedCount();
2 F# Y* r% }) ]: J - }8 I6 V- Z/ M7 A
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原7 b$ K% f% x6 ~+ g5 c$ C
2.新增- $collention->insert($array, $options);
复制代码- 新( W9 k; P; G8 }4 B7 h+ k6 m
- $resultOne = $collention->insertOne($array, $options);//单6 C* D" J7 o2 W5 I8 U3 _" `
- $lastId = $resultOne->getInsertedId();
9 P" x3 _* q2 M3 z* N+ S - $resultMany = $collention->insertMany($array, $options);//多
% H0 b& ~8 t6 Q# C; {6 | - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
; N" g/ P9 M) ~5 u& |3 m
- $collention->update($condition, [
8 l# T" B0 F9 l M' T - '$set' => $values
" O1 x" z3 N4 R; L+ r. [7 b - ,[
1 u6 Y, u# f& ?; K - 'multiple' => true//多条,单条false
5 T) M! @4 _- ?! Q( P - ]);
复制代码- $collection->updateOne(
/ X z$ P1 p" l, U! n - ['state' => 'ny'],
' ^% e2 J _- w - ['$set' => ['country' => 'us']]
6 J0 L5 K9 @8 u - );9 U( t6 k6 v2 J. N/ W
- $updateResult = $collection->updateMany(
* P3 G% f* k, @7 ` - ['state' => 'ny'],
" j, Y1 k% b9 n" c' u9 g - ['$set' => ['country' => 'us']]
5 j8 P$ [( G) J - );' A: `4 c: {3 F( T1 F' u
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [! Q7 H/ {+ [# a9 c9 |
- 'name' => true//指定字段
& U. `, Q* C" J - ]);
& p3 H# r i$ E$ Y0 N - $cursor->skip(5);
$ M; F$ F+ h% E% P/ U2 K- h - $cursor->limit(5);# M% {6 D# } t) ?
- $cursor->sort([
+ b1 h; i m2 v - 'time' => -1' u- c, t9 v9 Q3 W; o. f
- ]);
复制代码- 新2 s9 S, c/ {: |4 u) k. i7 X
- $cursor = $collection->find($condition, [
" |4 f9 h) o8 L! P. x - 'skip' => 5,, g( E: x5 l" U# R P; ]; K
- 'limit' => 5,6 C- P0 }9 L2 }% e
- 'sort' => [
$ a e- m d2 }0 T7 W - 'time' => -1
3 m( y* \" }- C: q8 D - ],//排序
3 ?! x B( n6 }+ q4 y - 'projection' => [9 g! I5 C) q. R- j" ]# X: h
- 'name' => 1//指定字段( H, C/ d0 n9 J& _: g
- ]5 N. K) f" ]* @; P
- ]);
复制代码 5.删除- 原8 c% `( u+ N) Q& s1 y! q
- $collention->remove($condition, [
: d: K' D; b. n9 u3 I; [ - 'justOne' => false//删单条
8 w2 c3 L6 ?' n6 r - ]);
3 a# q3 i7 i: W - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
* R/ s6 v( i$ F) O0 M" p" O - $collention->deleteMany($condition, $options);' s g% {( K+ l+ C, P# H
- 5 m& }5 q$ B$ \, K% {" w
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([! p; S7 W g/ m( `7 `
- '_id' => $tableName//我在自增表中用其它的表名作主键
1 k$ n0 q, _3 U+ ]+ k9 S - ], [; T+ ^& p$ X# T8 W# `6 D
- '$inc' => ['id' => 1]//自增& V( Q5 a' o9 W) d7 k
- ], [
0 o& t+ h/ v3 }1 e# X* p, \ - '_id' => 0, ^# C( E5 j5 f9 i7 T, |
- ], [+ ^9 i- W% m( v% S
- 'new' => 1//返回修改后的结果,默认是修改前的' Y$ m# {" z- s
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([# l& r5 W1 U) k
- '_id' => $tableName
; R9 Q J% O& V1 m' x - ], [
( @4 v4 ^, i% U( t. C - '$inc' => ['id' => 1]5 k3 v2 s" {% \5 W
- ], [
( J7 d, ?8 { Q% d - 'projection' => ['id' => 1],/ t, J( K5 x& `! @6 L- M* h
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER7 ^3 w( @# Q. o' s" y
- ]);
复制代码 # T6 x) M. W; i9 p X) f" \
e9 @" M) C# w |