|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
4 u' [( n* [$ h2 ~% u
" D" @! f1 d: _1 ?- use MongoDB\Driver\Manager;7 r7 J0 [& E. B: a7 E
- use MongoDB\Driver\BulkWrite;
! `+ s2 |: n; r# e. W - use MongoDB\Driver\WriteConcern;( p; E+ | D& B& i* h
- use MongoDB\Driver\Query;
) e) W3 m4 A8 g! L& ^ W- j - use MongoDB\Driver\Command; i, A. V; E8 e
# @. z0 i) d; I8 N: Y/ k- class MongoDb {. o8 j& I+ N% `; d* v
- 4 u! Y9 k4 f1 o# `$ N
- protected $mongodb;
# W) {2 V3 l: Z - protected $database;
# I9 E4 {, P% W o* F - protected $collection;. G+ h# |& f8 _* @" W' }& ]! x5 T
- protected $bulk;
& ? T( a* G0 A/ X; n r6 ]% C - protected $writeConcern;
* x- W% W% W' L5 x8 n - protected $defaultConfig
8 `4 v; ]: r2 s# V4 |, v/ @ - = [
. J# \- V/ g5 ~( y4 i - 'hostname' => 'localhost',
0 _5 R7 y8 ~& h" t - 'port' => '27017',
# B- i9 r* `7 T+ E: f6 v7 l - 'username' => '',& J& q/ ` }+ S2 Q) x+ m
- 'password' => '',- c! c3 Y4 v- h* V. Z1 f! o
- 'database' => 'test'
8 H: J; O7 v# O2 z* ]+ N$ X { - ];
) D% Z" S' G" o: L0 _ U - $ r% }8 ]/ j5 s
- public function __construct($config) {. V( R, r% m+ X, R; ]
- $config = array_merge($this->defaultConfig, $config);
3 X, O) a5 E0 U' j. @! X - $mongoServer = "mongodb://";1 z! v8 {! ]2 w ?( w! C8 F, m
- if ($config['username']) {
+ l% j% k% i" d# j. F: n. G9 [, K - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
, w, F' j n5 W" f+ C. o, e6 u - }
% Q! @. W5 R) p, C: } - $mongoServer .= $config['hostname'];4 h% |% c$ G0 I
- if ($config['port']) {
9 R8 i- U8 ~$ s p - $mongoServer .= ':' . $config['port']; Y" Y/ P$ F( }7 h* V
- }
2 B5 \( F @$ y1 J - $mongoServer .= '/' . $config['database'];* c5 u& N8 \) B1 | |
5 S( B9 s6 ]+ U) F4 g1 [" ]8 ~ q- $this->mongodb = new Manager($mongoServer);
- }8 Z/ l1 h7 c N4 F, i9 l - $this->database = $config['database'];
; U. D/ p9 I6 N - $this->collection = $config['collection'];
- J- m% i* Y) a! P, s - $this->bulk = new BulkWrite();
1 J5 w4 J3 t. e% L* Z. G - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
/ j4 [6 a* k+ V& P2 B - }) K+ v: o; u, i$ n( s2 h* C/ Y- ~
- % M4 V" q& |" |
- public function query($where = [], $option = []) {
B* R! `! n: } - $query = new Query($where, $option);4 u$ ~3 C7 [5 q. i
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);# W. A, Q5 s; b) f: T$ t( Z
/ l& ?- g3 G9 M* B) `$ V- return json_encode($result);* a4 t( P' J) y' d6 f
- }7 ^/ ]% u7 C; O" R# @$ c5 d
- # g$ R0 a' V3 G5 w& [' r+ k5 _
- public function count($where = []) {
3 R- y3 a0 f b. Z - $command = new Command(['count' => $this->collection, 'query' => $where]);& o% @+ b( Z& e; S4 a. n
- $result = $this->mongodb->executeCommand($this->database, $command);7 s' f. M& e! U/ a$ m+ N* q
- $res = $result->toArray();3 y1 ]! U3 f5 v
- $count = 0;' g% u" c( t [6 P
- if ($res) {
( x3 [9 @. V( B# y - $count = $res[0]->n;' a/ F: O$ h* |& U3 A! y. B, j+ k
- }
' l; I8 Y! N, j5 y" S$ t
( x# G" G& i. z: W- return $count;4 O6 Y6 {% T1 [# h0 {- B
- }9 h6 O7 b5 p7 V0 Y4 N4 y6 T( X
- 9 @$ ~$ e0 P5 W& P
- public function update($where = [], $update = [], $upsert = false) {4 e0 @; b7 N5 S" e, W3 |. ~, M
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
# s6 J3 S& e' P' B - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
0 O8 p, n# f* o/ j/ ^ z, k - ; Y* N# m, H& O0 ^. N7 {6 a
- return $result->getModifiedCount();
3 m0 p; H4 |3 T# t$ I( N! L7 h - }
4 Q; {! t( d, ]
2 o. D( r1 M' r% J- g3 N0 s- public function insert($data = []) {' R% A4 O& G9 X9 v" N: [/ H
- $this->bulk->insert($data);* x0 Q$ ?& R& A6 w ^* d+ G
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);4 I5 ^9 Z1 Q( v$ Z Y
6 v8 O- e" x2 ]& H- return $result->getInsertedCount();
+ z2 k# [6 g3 `+ y - }/ P/ S5 z2 n. |; b' S
- ' B) A2 }! D' D) |+ Q; i: A" |# O
- public function delete($where = [], $limit = 1) {
. W- H% A0 Q, J8 q# J3 u3 h - $this->bulk->delete($where, ['limit' => $limit]);! |1 Y( D' j0 ]1 G$ C" T- u4 k
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. @+ `0 ]( ~6 m _% v2 P
! c0 f' }* }( Q/ Z; ^# D- return $result->getDeletedCount();
8 o, U5 `# u6 Z E1 A, p - }
. Y3 }* I9 j4 p2 [5 {, Y' T - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
7 Z$ [( E" l, c4 G2 W. m8 Z$ q4 e
- 新' c* b) l' w( e+ s1 S K) A
2.新增- 原( |2 g$ t8 e" `9 P# N6 X% v
- $collention->insert($array, $options);
复制代码- 新1 h1 y# ^; V- c8 n9 N* x, Z# q
- $resultOne = $collention->insertOne($array, $options);//单, H0 @4 u: e N# ^4 E7 Y
- $lastId = $resultOne->getInsertedId();$ x& O7 Z4 a0 R
- $resultMany = $collention->insertMany($array, $options);//多" w" F8 g9 d5 [9 Q7 T2 k* n1 ]
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
) k1 a- t1 {2 |$ k u" G& W - '$set' => $values
8 K0 |+ ]6 s2 q w6 Y, `) f: _4 D - ,[+ k! U; m5 X1 T; `2 ]+ F
- 'multiple' => true//多条,单条false
4 I8 Q+ G8 Q- Q/ n3 L8 q3 B4 B - ]);
复制代码- $collection->updateOne(
( ~4 Q; m! G( c- H; _ - ['state' => 'ny'],' n5 J2 i/ Q6 G
- ['$set' => ['country' => 'us']]# n, s. X6 g& {* ?- F8 B0 @2 L0 k
- );- a! p' i- k0 H3 c- o2 J1 S: e
- $updateResult = $collection->updateMany(4 b6 g5 N3 b1 r9 J7 V
- ['state' => 'ny'],
/ g( L7 F$ y% o5 w) o - ['$set' => ['country' => 'us']]
. D, c6 y! Y) b5 [9 ~* o - );6 G& Z& F) B. W5 m+ ~ r
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原3 S! a+ d4 f. o& X! N' P( q8 v$ _. `
- $cursor = $collection->find($condition, [
( l+ `; h/ K0 C: I2 m! n - 'name' => true//指定字段
' } g8 s x: w1 [# c - ]);2 p; \# N9 Q# ^/ {( H2 p
- $cursor->skip(5);5 d6 o) } X& }* ^
- $cursor->limit(5);) N2 V9 O! j( L5 T
- $cursor->sort([2 D$ @$ @5 Q; J; q; @- n& S9 P6 a$ f5 [/ c# ^
- 'time' => -15 Y: |( `5 Y: s4 @/ r3 u! J$ ?7 w
- ]);
复制代码- $cursor = $collection->find($condition, [
2 _5 K% p1 d+ L* O+ T - 'skip' => 5,
' ]+ x2 ^! R3 G! p$ z T, @ - 'limit' => 5,: `2 w' d) ~4 g; a+ q
- 'sort' => [
" v+ o' v; |6 p! f8 {0 n - 'time' => -1
. A S6 A9 X2 M) G$ s - ],//排序
! d5 m! U! J+ W( H4 i+ R | - 'projection' => [
- T1 n t% f* U' y - 'name' => 1//指定字段. {# l6 U" c) [' ?
- ]' B4 W2 N" ~' ]( q( y* p
- ]);
复制代码 5.删除- 原& z. z8 k1 J1 z% ~9 X- V
- $collention->remove($condition, [
, r- s2 E- K/ i - 'justOne' => false//删单条3 C: I. _- L" k2 O! j( d
- ]);9 I6 I6 y" @! w9 Q. `
- $collention->remove([]);//删所有
复制代码- 新
" M h) h- @& g# B" A' ]
- $result = $collention->deleteOne($condition, $options);" R* y9 ^+ w2 ^2 [4 M
- $collention->deleteMany($condition, $options);) [! ?. [- q: W( W0 g5 n% c
- + o+ N' Z2 y, f. u# \! N
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([1 X+ h4 F9 A, _" a% [: U
- '_id' => $tableName//我在自增表中用其它的表名作主键
" E1 v) T; ]5 w - ], [
# f. |; D: N( J, Z6 `) b) H - '$inc' => ['id' => 1]//自增5 e2 H1 E# N3 s/ R. i! F. y% X) y
- ], [1 S) b/ Q- b2 l
- '_id' => 07 Q# q6 m" {& X* O0 F8 z5 P
- ], [
0 H* N1 b; a9 R0 s8 r1 X& F - 'new' => 1//返回修改后的结果,默认是修改前的
# h/ {! ]3 {, [, ] - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([: ~" p9 c3 t+ t2 x+ I8 ?) B
- '_id' => $tableName7 I. ^: @9 g5 C/ a% S
- ], [
' M4 F/ X( D) M) G& `8 p9 i* L - '$inc' => ['id' => 1] T! z4 _0 q2 K; o% l
- ], [
]/ w3 R2 f t6 y9 w+ P8 u/ a - 'projection' => ['id' => 1],
, Q6 w! d1 O3 R+ Q, j, G3 B, o% M - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
4 \. S! v+ H9 x# e! `" u2 c - ]);
复制代码
% ^4 e. R* r2 E" r' d0 f+ r4 b
. {' }2 E; b/ S9 ~( D |