|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
! P+ ] [4 D( ` - - H3 y' G9 U! L$ X8 {# N2 A _& m
- use MongoDB\Driver\Manager;
# s4 s' E2 d6 I1 o4 { - use MongoDB\Driver\BulkWrite;! Y4 s& m5 w3 W3 N; D! e
- use MongoDB\Driver\WriteConcern;: E) T5 B/ Q/ c9 R: C
- use MongoDB\Driver\Query;
, L% t& ~3 } f5 k - use MongoDB\Driver\Command;* Z; k, _4 J; d: k( p- Y
$ f' Q+ h0 d1 }6 ?& m. R- class MongoDb {- R6 w0 p8 s, ~0 H% R! x" m# z
- ! s6 K( G: a, W3 L. g: {* D/ [0 p9 J
- protected $mongodb;
! i2 r5 B# R, { - protected $database;- m6 r: ?# h# `1 ]6 ]$ f
- protected $collection;
& z# i8 ]3 }9 @* P+ T1 g, n6 G - protected $bulk;
2 E, P% u0 ]; g - protected $writeConcern;# e4 S. r6 l; h0 c3 r1 t% [1 W
- protected $defaultConfig
8 o" Y) A8 S5 s! F% @ - = [
2 u) H0 x1 ]! `6 b1 H# J* @ - 'hostname' => 'localhost',
# _/ h/ W2 {7 u3 U/ T( ]* O8 t - 'port' => '27017',8 ?/ F6 U4 n% R& b) E
- 'username' => '',3 c |+ }- N; w! d8 t H2 j) ^
- 'password' => '',
: U% I- `1 A3 o) Z' W9 {9 N - 'database' => 'test'
u$ g3 ^* Q, u9 C/ ? - ];! e9 p0 A [; w, L) ~: X
- # r6 e( @7 z1 j1 ^: b
- public function __construct($config) {
% F7 L3 D5 E& @$ [) G - $config = array_merge($this->defaultConfig, $config);. H2 R+ }( Z$ ^" D, ]
- $mongoServer = "mongodb://";3 G; Y( o- h5 A, f
- if ($config['username']) {6 e: H3 _9 f F9 L# f# r& c/ ]0 ?: H; P
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
/ M* ?3 L$ r3 E E+ P - }
% N7 _8 ^7 ^5 `9 W9 C0 j - $mongoServer .= $config['hostname'];2 Y: d* R, x3 U% W
- if ($config['port']) {
. \2 g* h/ |" w8 c' f. A" A- o+ T - $mongoServer .= ':' . $config['port'];9 X2 f |9 m/ T2 n) K
- }
9 T" r* ]( f$ Y - $mongoServer .= '/' . $config['database'];2 x+ H( j; a: S% \$ D0 n5 q
- ; t) c8 E7 f+ O! U. j; b }
- $this->mongodb = new Manager($mongoServer);+ n8 d- q' X% w" v z; B1 ]3 F
- $this->database = $config['database'];
. |# `3 ]: {9 _$ ^: U - $this->collection = $config['collection'];! f. `2 E/ w+ k J
- $this->bulk = new BulkWrite();' N1 m9 X# U2 B( R5 n
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);4 w( k+ n# i$ f
- }
2 w" A) `3 f( h4 I( O3 |% U" Y
7 S7 |1 @! y {: @8 F7 r3 T- public function query($where = [], $option = []) {
2 @- o7 t8 A' I) y4 U$ L# E/ C - $query = new Query($where, $option); E# \0 e5 \: c7 C- G2 B1 f
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);* {9 T7 I# S* x6 e3 V
- # O% U% `6 l; A5 G9 h3 F
- return json_encode($result);* H# U) g4 a4 w* Y
- }3 f! d, G) w& ]$ X d: Z0 f1 @# }
1 z5 a7 J/ @2 [7 b+ ]6 u; W. W- public function count($where = []) {! ~! M* m2 V* L3 k3 @* m! H! T2 J
- $command = new Command(['count' => $this->collection, 'query' => $where]);
. P' U5 E8 e+ N: C% f. p - $result = $this->mongodb->executeCommand($this->database, $command);
+ d0 H$ P6 |1 S9 f! j - $res = $result->toArray();
7 ^+ G9 S% X4 \; Z% K7 i q+ g - $count = 0;
. ?) Z# n7 @* a1 b* r# d' K2 @) g - if ($res) {6 l# I/ l W9 b( }: M
- $count = $res[0]->n;
1 K0 Y0 p0 K1 g" g1 { - }
9 s( w+ ]# X e5 |; J
7 R5 R# x8 _6 V. X8 D& j- return $count;6 [: p+ @1 r4 A4 ?# y
- }
1 E- ?' _" J! }& r. q - : W c9 ^9 e" M# K/ O6 E
- public function update($where = [], $update = [], $upsert = false) {% V* p/ Z4 R: S: _8 ]( R) v1 U$ o0 E
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);, l; _) {8 \! T* _5 C$ h0 D$ s
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
$ B2 R% F: t5 d) Z4 n0 }
" v( c( v( M# ]8 T- return $result->getModifiedCount();* F6 X; o; q i. b- a
- }
0 o9 y3 y" ?3 y1 ]% L, X! b- l" m - 2 w! m! M0 q z7 t
- public function insert($data = []) {
- d0 ~+ Q( B3 C4 k/ s) S - $this->bulk->insert($data);5 @2 n# |1 J# d6 b* g
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
+ A( h% i7 T7 m2 k* @0 t) v1 O
' q% `/ a, M1 r( \! i3 p- return $result->getInsertedCount();
" R8 ~9 `! g+ M. o- @+ V - }# O1 k R+ z6 f0 G* s
- 9 S3 @: ^) c' n, i) n K
- public function delete($where = [], $limit = 1) {2 u. X& b% @+ H: a
- $this->bulk->delete($where, ['limit' => $limit]);
! f0 |2 M' {. l- k! [. E: b - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! N- d! D$ R! @2 J
+ _* Y: D" i$ p C8 z; \& a- return $result->getDeletedCount();7 I5 B3 s& ^) U7 T0 z- X
- }5 B. h H0 f s) M
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
7 u* u4 S4 t! o* M% ?6 }; I 2.新增- $collention->insert($array, $options);
复制代码- 新
! ?; ^ Q3 A0 B. ^1 k9 x; e
- $resultOne = $collention->insertOne($array, $options);//单
" m3 P/ f6 i: B2 a - $lastId = $resultOne->getInsertedId();: r! s5 l' v, I% z u
- $resultMany = $collention->insertMany($array, $options);//多
8 W5 u; k N8 d - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原5 X8 d, t$ y2 a8 e, c4 ^3 Z
- $collention->update($condition, [
: b0 Y2 s" P) k$ I9 _ - '$set' => $values; [, g- M5 X9 F( r6 w: j) h- _# \
- ,[
3 U1 ^/ A. `" a& B% k - 'multiple' => true//多条,单条false
7 U8 C) v1 x' ~6 r- v# h" K9 ?$ a - ]);
复制代码- 新* p- s) G; d( z8 R: T: v
- $collection->updateOne(5 W' C0 ^1 a' k4 ^- o3 a8 e _
- ['state' => 'ny'],
# }3 M. X9 q5 g. a- A8 g1 s u5 R. t - ['$set' => ['country' => 'us']]
0 k9 [7 O2 C: Q3 y - );
8 O! \- _, d# F" H4 m4 A - $updateResult = $collection->updateMany(3 X& Q( f9 A& m' I, w
- ['state' => 'ny'],; l; m2 }( I- m. }
- ['$set' => ['country' => 'us']]" R, k7 \2 B$ [) U
- );
4 Z! g0 \) i6 _% O! N {& | - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
* [/ U1 F( y/ }$ y' {3 l
- $cursor = $collection->find($condition, [
) m$ H) l( X6 P: q - 'name' => true//指定字段% Y* k- q$ M: V$ [ O7 K5 v" U
- ]);$ Q+ E; p: y* L3 [- Y1 m
- $cursor->skip(5);$ Z5 i: p7 v4 Y' `. W: X4 @/ j
- $cursor->limit(5);1 _# H& I6 C% ]0 p
- $cursor->sort([# _: Y3 x* H1 R
- 'time' => -1
. j& b" t. v* T& L3 ?8 M - ]);
复制代码- $cursor = $collection->find($condition, [# L, K* ^ O- x. I; d9 j
- 'skip' => 5,
- D" {) v2 F- Q, w6 H; k* Y1 H - 'limit' => 5,
* P4 {, Y, p5 F4 U6 A. o - 'sort' => [
# X' Z; z6 |* E8 j3 B7 {6 Q - 'time' => -1$ p- c5 A1 Y- u- H$ t; F$ H5 G
- ],//排序
% V# ^% j' \& {2 g1 J7 o - 'projection' => [) U$ J* D9 }8 g
- 'name' => 1//指定字段
( F! K I8 G) Y3 v - ]
B# W) g- L9 S& s* z! F+ Q - ]);
复制代码 5.删除- 原% `4 A8 J: i( Z9 Y4 k e6 \" c
- $collention->remove($condition, [5 ?) D i1 E' Y' l
- 'justOne' => false//删单条
) N0 X8 Q; s B2 B3 D& }4 D - ]);+ v. O0 I# v5 Y+ Q% A. j
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
; {3 D- h0 [4 `- Q* K: Y2 l% I - $collention->deleteMany($condition, $options);/ k- R9 W9 A% I2 g, q+ E
- ! j" H% m* h! `3 h7 w! x
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
6 Y# y5 N3 V' N, U5 g - '_id' => $tableName//我在自增表中用其它的表名作主键
3 f7 z1 ^" j6 M2 h1 n+ J - ], [
$ d4 c, d2 d$ r# }9 g2 _. _ - '$inc' => ['id' => 1]//自增
+ K; G/ J2 x* u$ K8 ^. u# g, l - ], [6 Y9 q8 e; j- V# n( Z1 M8 X
- '_id' => 0( d+ K/ I% o U
- ], [
, `' P2 V# R$ t7 U - 'new' => 1//返回修改后的结果,默认是修改前的
$ ~0 C( c( l5 Z# R0 Z - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([+ {9 F: \- |: m6 M
- '_id' => $tableName- Y! a" d- v$ S, R! Z
- ], [
! l% T2 ^9 A- A - '$inc' => ['id' => 1]
" ? i u9 Y0 X! D3 g - ], [
! m& }" A/ ?( P: Y( \ - 'projection' => ['id' => 1],0 V$ x/ E0 r) R) X; i1 _: k) y5 {
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER3 l* m! f' }! c# ]8 y' h: D- ^9 W7 Z& Y
- ]);
复制代码
& \ w& Z% R% N+ g; ]: \( u7 Q) H2 W! l. W7 F
|