|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php# ?! u4 h$ `1 P2 m8 s/ x9 R2 ]* w6 v
- 8 r# ~& m( i+ z& V
- use MongoDB\Driver\Manager;
) i6 r" N0 @& l5 G* m- f) U - use MongoDB\Driver\BulkWrite;( |! c6 I- S: I9 b& P, u/ I7 w
- use MongoDB\Driver\WriteConcern;
8 Y* ^) R) a$ D! R- t. G - use MongoDB\Driver\Query;1 T+ c+ R! y9 F9 Z
- use MongoDB\Driver\Command;
u+ \. }6 Q+ W8 m: ?7 D) Q4 \
% \" l8 B7 M/ G; m0 S0 C) i- class MongoDb {: l, s9 C2 Y, r. ] A
- ( }/ T* M4 I! ^" s( y' B) E9 O0 ]: A4 @
- protected $mongodb;
) D3 F4 R) y- g+ R) O1 y - protected $database;
+ @- ]; `/ P, [6 J( k - protected $collection;
0 g& ~7 l1 Y0 p F# L - protected $bulk;
% l, x& a; N9 v& S4 f - protected $writeConcern;6 X3 |5 M" F1 W* G2 V
- protected $defaultConfig
, y* e# Z. O" w: ~; E: }. [ - = [6 }$ h8 g1 x1 I" Q. p
- 'hostname' => 'localhost',8 G% W8 D" H/ T; u; B w
- 'port' => '27017',
3 W" p* N1 e" ~2 I, d - 'username' => '',5 f/ y! g9 U* H7 k8 z0 p$ `
- 'password' => '',
5 _: q& }' g9 |2 a - 'database' => 'test'. B! P/ J/ b2 s
- ];
0 G0 Q8 |! m6 e$ }$ U. H1 `( ?
" U# x+ {5 d) ^- `- public function __construct($config) {, O9 n7 r' [, n$ v3 I; W
- $config = array_merge($this->defaultConfig, $config);
" T0 U# s T$ c1 J2 k) M* G - $mongoServer = "mongodb://";0 N/ I | ~! B" a. q% S% [1 C1 f
- if ($config['username']) {6 i; Q+ W/ \7 N) B* f4 P6 G
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
6 m/ e& \0 }1 r2 S) l - }1 L6 O o( ^0 ^3 W- Y1 c# u
- $mongoServer .= $config['hostname'];
9 Q" R" B8 `6 k4 S2 b - if ($config['port']) {8 D$ e% E1 L( f; x. R6 @
- $mongoServer .= ':' . $config['port'];3 I1 R$ S8 U( M& }: R
- }
C( g4 L+ T; U* L% A: Q4 b - $mongoServer .= '/' . $config['database'];
4 q/ q/ Q) u) F' W9 V: a$ T
# F. L0 i8 K9 z- $this->mongodb = new Manager($mongoServer);
! z N0 M$ Z d8 z - $this->database = $config['database'];
" X9 L V1 a1 P6 n* J; b0 t - $this->collection = $config['collection'];
/ r, F+ ? B' k- h5 @! x0 ?/ i - $this->bulk = new BulkWrite();
3 Y8 m& }! W2 w7 a" x - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
- H" W w: N* d0 i; ^0 r) H* |3 { - }5 ~" ~* k! N' i) b) T4 L, O
- , y: b+ r, j" } O! a0 U/ u; d
- public function query($where = [], $option = []) {* I. e f, j/ L& l; [
- $query = new Query($where, $option);
! ~+ J% D: q& i4 o8 h - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);! I! ]1 Z3 i4 ?4 o) J
/ E/ ~1 M |: j y$ g- return json_encode($result);) N2 v7 |& F) x; r. {1 p
- }+ m' T1 _% j- j% S% Y, H0 m3 a
- ( j+ O2 s6 D+ _1 {" n* y2 u# V
- public function count($where = []) {. t% D6 k' D# P3 V. y5 `1 B2 [
- $command = new Command(['count' => $this->collection, 'query' => $where]);$ ?: h' m( ~7 z& J4 j7 @( T+ ~# w
- $result = $this->mongodb->executeCommand($this->database, $command);* K7 M0 z2 ^. D o
- $res = $result->toArray();/ F" g4 k8 M) _
- $count = 0;
L, T; ^) O) I6 t$ D0 l' W8 Q0 a - if ($res) {8 D5 ]* N' c3 S) j5 b( w2 ~
- $count = $res[0]->n;7 S4 L) Y+ @3 n* [% `5 R0 B: K
- }! `7 t2 V( c5 a& t) C" Z; s
- 0 o7 R0 S6 U, F! e3 r9 ?. }: }
- return $count;
' w, }1 k* K+ z% w- p$ M' h - }; [0 s/ N2 ? m$ x9 _
) W6 u+ s9 k, a+ H- public function update($where = [], $update = [], $upsert = false) {
- ], s, ~; S B" Z2 j# { - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);1 z; h" R1 K: \; t7 Z1 k
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
% y3 u% h5 R# m( m
3 ]; F. W, x* `9 w) H- return $result->getModifiedCount();! a- D2 v$ v0 V: f! v. i$ A
- }
* z g5 W# @5 M" ?9 _5 y- h/ t - 9 Z; @0 X+ I- w9 v( a0 Y5 k
- public function insert($data = []) {
! R0 a& c l6 M! |* G! ?. ~& U - $this->bulk->insert($data);
) H; q1 e/ l. Y3 O' d - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);7 }$ d# @9 I" ^% Z1 \2 K4 _0 e
- 0 {9 @- Z5 R* B4 t' s
- return $result->getInsertedCount();3 v* c$ |; a2 D6 h9 G
- }" e% m0 d0 I( r) ?3 V' `- g, `
- 2 ]; ~, M+ j* [
- public function delete($where = [], $limit = 1) {
& n) `* A, D! {, ` - $this->bulk->delete($where, ['limit' => $limit]);
* n! l# j+ F2 O6 P0 \ - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( i; ^7 C- f/ ]) Z& Z% Q { - 5 h9 o6 m: R& u% k% s) b* Y! D
- return $result->getDeletedCount();
7 y4 h8 U/ }1 Q; Z - }- x& [/ E, {$ V2 [- T' ~
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
9 i: w( o8 b) G! }; a5 M( O
- 新& ]* B) {8 }( v5 ^5 Y0 V% [7 ]+ S
2.新增- 原9 i; z: |6 F- U0 y3 u( }8 [
- $collention->insert($array, $options);
复制代码- 新2 P1 | p- {, c8 |; {8 M9 X7 f" B
- $resultOne = $collention->insertOne($array, $options);//单 |- z# c) D: N5 f; m* b7 t: Z5 H% P
- $lastId = $resultOne->getInsertedId();
% H4 G9 w R* i2 ~7 c - $resultMany = $collention->insertMany($array, $options);//多" ? b$ d' @4 O4 P# q/ A
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [) \/ N( Q, o' b
- '$set' => $values
3 y% w) H- M$ f) F, @. ? - ,[
$ V8 R! j6 {7 @$ F3 e1 y" V p9 Q5 ? - 'multiple' => true//多条,单条false
& r6 i4 q& ~* l' |1 ^, I3 ? - ]);
复制代码- $collection->updateOne(* w# A$ w7 m$ ^" d/ s
- ['state' => 'ny'],
6 q1 ]/ ~1 j$ w - ['$set' => ['country' => 'us']]
' w5 P$ v5 x2 U2 U5 a - );
. Q L6 t6 K7 b6 u( T( p" K. C r - $updateResult = $collection->updateMany(
3 y1 n: O+ R7 ? - ['state' => 'ny'],
5 S! R3 b! g+ t- o1 g) y! l - ['$set' => ['country' => 'us']]
4 v1 e% g8 G* T8 r* U8 }$ s: }( R - );
1 K7 K- T4 B C3 f& V; M( R - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
/ J. S( R3 V( }! \; L# L
- $cursor = $collection->find($condition, [
- g! W1 P( x. s5 O. _9 n - 'name' => true//指定字段
' ]) C; ~) S& S3 L2 k - ]);
7 l2 ]. N1 ^1 V; A9 D) ` - $cursor->skip(5);' y; m3 b+ ^9 ]/ |% e
- $cursor->limit(5);
5 |' q& G5 V3 O! n6 D. s - $cursor->sort([
) b! |5 @$ l. O4 { - 'time' => -1
* u5 f- q, F, B& {# Y - ]);
复制代码- $cursor = $collection->find($condition, [
0 o! k" o2 Y5 a3 e! I0 N& N5 g - 'skip' => 5,4 o) S% x0 }; U" ~ d% q$ \* o
- 'limit' => 5,5 N( Q& d3 r4 D4 S! r
- 'sort' => [6 }/ Q2 v6 L. P: l# {
- 'time' => -1
. ~' L$ X9 F" u( ^5 Y; @ - ],//排序3 b3 i8 l! T- A6 s' }! d8 q
- 'projection' => [
1 y+ }* ?. F) r' e/ |4 e. D. f8 E( s# ^* v - 'name' => 1//指定字段6 P5 t+ R Y- s4 G9 U' h; ]8 Z
- ]
/ Y( t9 l$ i* Q% y9 o - ]);
复制代码 5.删除- 原
6 t2 \% m& y6 j) n. D. H
- $collention->remove($condition, [
2 P( m0 {2 r' l' B- h* `2 _ - 'justOne' => false//删单条
' {, D! T( }9 w( |9 I - ]);$ ?$ ^2 }) p; y/ y3 d+ [0 e* V" l
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
8 R g% M7 B- i: A$ |6 [# z. E - $collention->deleteMany($condition, $options);
' g4 f$ ]$ Z+ c- O& M3 Y; r5 J
, H& Y. p9 k# |& v6 B% e3 e8 W/ D- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
p G/ `: |. ]7 c9 U% p" A9 @ - '_id' => $tableName//我在自增表中用其它的表名作主键! z5 r1 D9 h/ X/ F+ N7 ^, H
- ], [4 Q7 T: `7 I- T$ D- o# _
- '$inc' => ['id' => 1]//自增" R! I+ ^( I8 A) \. I
- ], [ t# [% u d: l2 U+ |/ M& _: k
- '_id' => 0- l r" \! ^ G8 b
- ], [
& u( D( W/ n* Q( a8 E0 a1 ^ - 'new' => 1//返回修改后的结果,默认是修改前的$ u3 U! d0 g2 g# W0 h" Y
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([8 G8 z+ N& I- G) |7 I
- '_id' => $tableName
2 a2 U2 D$ R9 P* L! L( a - ], [0 _6 J8 k% Q3 m+ ]5 X: g; h1 e4 o
- '$inc' => ['id' => 1]
& v6 A t {' U: Q0 ]. r9 V$ P6 Y - ], [
. ~ d5 p [7 P- R! { - 'projection' => ['id' => 1],
* c- b2 _' k$ f4 c/ C6 ` - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER- P5 s+ `+ t/ D1 F0 _
- ]);
复制代码
s2 y' D W# E6 G- y! i3 z" \- C9 f4 R5 O
|