|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
. o4 e/ D. r, m R4 { - 7 e( Q7 C" ~* w
- use MongoDB\Driver\Manager;
) s+ q( G+ L2 p- R: [5 Q - use MongoDB\Driver\BulkWrite;
+ Q/ f: r) N4 }' Z. h - use MongoDB\Driver\WriteConcern;
2 w8 T3 B6 K' P3 |2 }& Z - use MongoDB\Driver\Query;
, k% E: P( Y$ s$ h/ S# s6 k - use MongoDB\Driver\Command;
% Z) E- M% C! @* c - & n+ H V3 c) Z% ]7 B7 \
- class MongoDb {0 H- K+ q! w/ B z# W
- 9 ?- H f$ M* m" P4 x& O/ z9 D
- protected $mongodb;# p A, z( t) \
- protected $database;. j: g* f3 k Y+ l) Z- o
- protected $collection;
. L$ \) U0 J& ]8 d0 K - protected $bulk;
% |' G6 P! p8 z6 P2 r; L - protected $writeConcern;
1 W* k: ^' I+ b+ r. \5 y: I - protected $defaultConfig3 [2 E) f% z! q
- = [5 ~" d8 v* Z8 y' _* T
- 'hostname' => 'localhost',
3 [. G$ x/ U& s b; h - 'port' => '27017',' x) y4 F# Q# e; N l! ~
- 'username' => '',9 Q4 {6 L( m) C: q
- 'password' => '',+ B2 _. W( q- l1 J' W& ]1 X
- 'database' => 'test') j( q5 h( e2 k0 N5 ]2 S- N
- ];. n0 ?% z1 {( A) W7 u- `3 e
7 _5 H" Y7 c1 c H, ?- public function __construct($config) {
- V! ]8 C3 T! D; L8 m1 Y - $config = array_merge($this->defaultConfig, $config);
4 z E6 b: r4 m - $mongoServer = "mongodb://";
2 }/ ~- v! V S6 m: o/ f - if ($config['username']) {
. X& \8 f! y# ~0 ~ - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';! L) K1 S$ l- x3 y6 b
- }8 i( K2 J/ d! F' K& ]) [! p. b: a
- $mongoServer .= $config['hostname'];
0 ~* ]/ w6 t' H+ H- S - if ($config['port']) {
, H/ q M# j, c% J1 [: K7 Y - $mongoServer .= ':' . $config['port'];
* l; ]: d9 V+ E; Y& N9 s% ? - }
" a1 k: V; S! U4 ?" v - $mongoServer .= '/' . $config['database'];" w7 w# J: }% ~! {0 w( L/ P9 e
, Z( M! Z( u( S# H- $this->mongodb = new Manager($mongoServer);
: c- t3 F4 K: N - $this->database = $config['database'];
2 o3 k' W( G! S, @" |9 K+ m - $this->collection = $config['collection'];
/ I2 K' R7 F& m' |! D - $this->bulk = new BulkWrite();3 h4 |# @0 i; @: }" O
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
" W/ _$ Y y- } - }5 h* d9 G7 a5 i& ^) u9 i1 u% j/ e
- R3 ?! j2 L( O! L/ b
- public function query($where = [], $option = []) {
( O9 j) N1 C' Y B- d2 g& h6 o - $query = new Query($where, $option);9 m$ r6 o% ~/ y9 T
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
7 C6 n5 }" f. H7 ~) |% _
) A1 C( ~, ]* a% N3 t- return json_encode($result);+ a3 ]7 L( q: h+ ]5 v
- }1 l7 e4 k* x7 T8 l8 G* w; Y! _7 W
- 7 V6 U& S' e) a# U
- public function count($where = []) {0 @+ x) U1 i- U4 ~4 ^* M6 `, T
- $command = new Command(['count' => $this->collection, 'query' => $where]);0 q3 K5 F9 B2 j* T' N3 i& J1 `! Z
- $result = $this->mongodb->executeCommand($this->database, $command);
5 A) I, {8 i: S9 z- n$ z - $res = $result->toArray();
% g! N; v% R! M2 \. F4 o; S - $count = 0;+ K; N; H" r' R& Q+ A6 ?2 r
- if ($res) {
0 G8 W2 z) a, u1 `4 o! ~8 g' J - $count = $res[0]->n;
w% k; x! {0 f. g5 M - }4 _* w+ a8 N l! g
/ _" |, g3 G& T& S8 P& n- return $count;3 _+ y" k2 ], J2 M
- }+ y& y; K3 s2 {$ k2 M5 w( S
. x5 x+ D4 X6 D6 @6 m- public function update($where = [], $update = [], $upsert = false) {, L4 d( E4 R) C) s- q2 e
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
9 r/ B$ l5 q( V: `7 ~ x6 W - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
+ j5 A# M! }& R; q" F: Y n - * Y) C; h- L' l/ O/ j q
- return $result->getModifiedCount();9 Y0 r. f) I' a/ q! l6 ]4 f& K7 ^
- }
+ x" B; ^- l) z0 |* N4 M - ! }& F6 |5 ~2 _
- public function insert($data = []) {
1 s) ?$ z! O, M: h8 e; J - $this->bulk->insert($data);
5 ~+ w- W1 c7 L/ r, \" t - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);% o* i; ]3 Z1 }( j9 w+ V) |; B
- " Z K# r: Z8 D# [: ^
- return $result->getInsertedCount();
9 {4 \) s5 _3 L - }
" p" k9 T7 K! N) B6 O1 Q; M8 d
+ ^& P( d' w: Z; G* j/ C- public function delete($where = [], $limit = 1) {" y& m" D Y! M
- $this->bulk->delete($where, ['limit' => $limit]);
5 n# E, O& Z3 [* i0 r8 _1 q: ^' B - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);5 s; L, S3 f Z1 m9 y* N
, Y% a n I0 [- Z: `- return $result->getDeletedCount();; N' f' n# n p. Z% S' p& a/ b
- }" _5 G( H+ ~, y9 Z5 }& R7 T' P9 J$ p
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
- a5 H' r7 }; p* n% U1 W2 c 2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
- t( j; a$ W: R; B& i* {. A - $lastId = $resultOne->getInsertedId();6 ?" h0 ^; l7 K. Y$ I m" k
- $resultMany = $collention->insertMany($array, $options);//多
% Q7 c$ s. u! t+ a$ _( o2 L: ~. r - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
2 \& C, q0 B5 g" O& Z& q" A
- $collention->update($condition, [
2 n, p( ]0 H0 F) Z6 G - '$set' => $values
4 k9 f' n/ V0 J& U) U* f9 X- g7 q& }' l0 T - ,[
2 \3 e4 o. V' o5 t( W - 'multiple' => true//多条,单条false; t' g" q" N+ g' F5 U. `+ r$ F* N
- ]);
复制代码- 新4 q( S1 ~7 l. R2 Y6 Z0 a4 |
- $collection->updateOne(
; z0 B( k# x4 }9 G - ['state' => 'ny'],( e: h$ H0 ^6 @1 V
- ['$set' => ['country' => 'us']]
! V$ L7 l5 O- S" T6 F: M! J - );
. N9 @. |% q( V8 j( t8 I - $updateResult = $collection->updateMany(
2 s; g2 q: s2 z - ['state' => 'ny'],& ^5 g; W! ]3 v5 H
- ['$set' => ['country' => 'us']]7 g# d! H, ]5 o( v
- );6 Y+ A; f$ m/ F' _: D( g
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
* \4 C* D! m0 C0 T* j9 e - 'name' => true//指定字段5 ~4 K# V' F# |6 B+ Z3 c
- ]);
2 g( M- N7 {6 R2 |+ v2 L! h: ^$ u - $cursor->skip(5);6 d0 h! u0 @3 i9 I
- $cursor->limit(5);0 w% o) L/ Z4 v2 B! ?; q% A, ?+ O
- $cursor->sort([
, {9 t/ p" i5 o+ `0 }6 ?6 k+ q - 'time' => -1
. G* o7 {2 I$ b7 } g - ]);
复制代码- 新
4 f3 E( s1 b% n1 ?+ ~1 j
- $cursor = $collection->find($condition, [3 d- h" T; Z# ~
- 'skip' => 5,
, H1 R, f" w2 d1 d - 'limit' => 5,
, E+ a5 i& R) V, m& S - 'sort' => [; \ V `; s! h/ ~# Y x' `
- 'time' => -1
1 r% P7 I$ C m9 J5 C - ],//排序. }. P0 y9 r+ Y$ @/ ]; t! P! u
- 'projection' => [
+ p+ F- C" M# e& l) T2 q - 'name' => 1//指定字段
3 W5 R" P1 x; ~7 i2 ^* C3 x% v* T' G - ]- @9 Z7 l; d# L+ i
- ]);
复制代码 5.删除- $collention->remove($condition, [
, _* D+ O. N* ` - 'justOne' => false//删单条6 @7 G9 N% j+ r: y' o- n: a( `
- ]);
4 n3 b) ]: T; n1 x$ x - $collention->remove([]);//删所有
复制代码- 新
+ [3 A# u( C; O/ ^3 J+ }' I
- $result = $collention->deleteOne($condition, $options);
# w8 m4 i* f! ?8 W- q - $collention->deleteMany($condition, $options);. V' @, z6 V" Z$ V! o8 Q8 x
- 8 l, A0 j! L% _+ e7 f1 b
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([6 Z: _5 M8 S, O: m
- '_id' => $tableName//我在自增表中用其它的表名作主键
, y* m7 L6 ^9 U - ], [
5 L4 Z& e/ a5 x1 g, _ - '$inc' => ['id' => 1]//自增4 p+ ? V8 N2 a' @% w' \
- ], [
+ r2 I; u3 ^$ P* R! s8 m! | - '_id' => 0
3 A& V, g) W# L - ], [$ h) y4 C0 L: V
- 'new' => 1//返回修改后的结果,默认是修改前的2 Z# F. y5 O3 A1 [4 c3 X
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([ N8 b# B& ]% ]* f5 O
- '_id' => $tableName
* A% F0 T& p( U: Z0 C4 v4 M4 M! e* a - ], [
: ]- e& F. N- k! P- g - '$inc' => ['id' => 1]
* ]" y6 y7 a x* \! z/ l - ], [$ m. p$ m6 k; w- ~3 T' n
- 'projection' => ['id' => 1],
- j* B% H" l3 ]6 d - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
+ }( N* r* \" \' Z# P - ]);
复制代码 6 e% y' b$ ]2 m* \9 j1 w3 L
; Q9 i @, {1 v: U" \% l6 z l) A |