使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php7 r- f+ W8 `7 ]* C
- # J8 q0 G2 N: ]$ P# m* Y
- use MongoDB\Driver\Manager;. A% U2 R# L+ \+ }0 P4 r2 ~. |
- use MongoDB\Driver\BulkWrite;$ p! i% s! p7 n6 `
- use MongoDB\Driver\WriteConcern;
3 P: i$ z0 |" W3 I/ d4 ~ O - use MongoDB\Driver\Query;3 {! @9 E' _4 N& p( S0 Q$ g+ J
- use MongoDB\Driver\Command;
V) ~( \- h: [6 ^5 I0 y0 w% T3 ~ - # K' C$ M* I% J6 I$ Z
- class MongoDb {
1 d' S9 \' r1 s* D! L$ H& [/ V% F - ) z8 y4 p. `6 p
- protected $mongodb;( M4 i* `* e. ]* W- j) r4 Z
- protected $database;/ p5 Z1 U% Q" \
- protected $collection;
4 i( h: @ p. V6 \* S/ O0 T - protected $bulk;
& R. S7 O& e+ | - protected $writeConcern;
4 C: n9 `9 Z% s2 I - protected $defaultConfig
$ h( _2 Z6 {8 l* b2 R - = [
4 s8 O0 }; S1 k - 'hostname' => 'localhost',
J0 o6 `( V0 b: a - 'port' => '27017',
$ b% K' s: B3 ^ Q - 'username' => '',
3 b8 g1 d, n3 t8 e - 'password' => '',
* ^* D3 q: v6 a z+ k* z - 'database' => 'test'
. J. d5 b+ w+ D' F3 w - ];+ y* g$ v! z, C2 l! ~$ b
- 8 Q& R7 \9 K0 G1 v2 L W0 O# M# s
- public function __construct($config) {* L3 q6 T s+ c' A: s. | ~9 m# z
- $config = array_merge($this->defaultConfig, $config);* h+ |0 ~8 H, s" C- a4 w' d% k* i
- $mongoServer = "mongodb://";
" w2 |1 n. }3 L - if ($config['username']) {
/ {0 J" p8 }# d" f4 e z9 Z - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
1 \: N# ~' l# n) m - }" j! g3 l$ o+ g/ ~
- $mongoServer .= $config['hostname'];
3 P l# T" k8 x" R1 @2 ~ - if ($config['port']) {
* l& x' d! \2 t! h M- E$ M- L - $mongoServer .= ':' . $config['port'];
8 m# ^) e8 i- w - }
( V: i) J( P4 q6 f, V$ w - $mongoServer .= '/' . $config['database'];
1 K1 Z, g S2 X$ B& B( @ - ! _* X5 k0 v$ }6 I( X z
- $this->mongodb = new Manager($mongoServer);
+ t" U' x) y7 } }1 _/ X2 e- b - $this->database = $config['database'];7 l; ` ~: \: p! a' N
- $this->collection = $config['collection'];& V" z7 R9 a' {; B: e
- $this->bulk = new BulkWrite();
U2 `/ B, N: e" c5 D - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
0 w( l, u5 X, i; s7 Q& u: t# c - }
2 ~! r& w. T! U* j- P: L: c# W
7 y1 R& x& Y! |- O+ n) ?: F- public function query($where = [], $option = []) {+ C7 C6 e; |6 X2 R
- $query = new Query($where, $option);5 l: H0 _. W/ e$ P7 q; r
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);4 ?8 M4 Q% v3 |' J( }
, g' N6 A* r5 E1 W) \9 \. x- return json_encode($result);* r2 R, M; s8 f0 \
- }
+ \" o1 h% E4 ^6 x4 I4 H/ i
5 \1 g0 N5 P) L9 B8 i5 l- o( u8 }- public function count($where = []) { P( Y8 F1 _4 x: C, n, O w
- $command = new Command(['count' => $this->collection, 'query' => $where]);% c- t+ w% ]* G! o. Z) ^
- $result = $this->mongodb->executeCommand($this->database, $command);
( e1 N) J; }' a" K1 v* j- y# V* F4 b - $res = $result->toArray();
/ l. N/ l6 _( `- A - $count = 0;
/ L# {( d0 F# n: r: G - if ($res) {
& W' x9 l; G. |& C7 b - $count = $res[0]->n;
3 Z |7 J( f6 z - }
9 p- r: H, g5 m/ e( @6 l& w
8 l8 U# ^3 H3 K/ \) e- return $count;
0 \3 P9 Q3 v& q1 \ - }
& z. r) v- {6 f
% ]& j" V) S/ }( @& ]- public function update($where = [], $update = [], $upsert = false) {
1 j8 `0 J; |4 T3 M9 y9 K1 g- l - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
; z+ V# J$ g5 ~3 w - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
2 d1 s) u7 A# w; d' N" r3 n; S2 F - 7 P/ D1 |. ` F/ W
- return $result->getModifiedCount();
& v" j) {4 r! S9 r* A - }7 M2 m! o8 V6 L
3 w, U, ~! \/ P1 _+ Z7 _- public function insert($data = []) {" u- g# ^9 t* C3 L# D
- $this->bulk->insert($data);
! r. P) q1 h& K) K3 \8 ] - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. Q" l" H& {& F# f) i
7 R$ U5 |* Q; [. O+ _: n- S- return $result->getInsertedCount();4 y3 j* F/ i; |- O; [% {# P/ d
- }& A* _8 q! `5 h |, A* n! q/ I
1 ~, S) N/ i/ T. M9 Y- {8 P- public function delete($where = [], $limit = 1) {2 H. k: f8 Q3 h4 j) o0 w2 E5 S! R% o
- $this->bulk->delete($where, ['limit' => $limit]);; A3 d% ~4 e4 V" @! F
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
) N2 w8 G& N; l' |* @
9 k- K7 p0 F1 e0 a- return $result->getDeletedCount(); K/ j# l, c9 M" e: \8 V
- }
7 n# i6 L8 x# q2 C7 o7 v - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原( w$ V4 N5 n- P; S+ W3 E5 J
2.新增- $collention->insert($array, $options);
复制代码- 新
( M& o: z2 y9 @6 G& Z5 Q0 F0 z
- $resultOne = $collention->insertOne($array, $options);//单
5 h {4 _* y6 t7 H* ^ - $lastId = $resultOne->getInsertedId();
) F6 P9 t/ W& G2 Q8 U1 k - $resultMany = $collention->insertMany($array, $options);//多
: J4 g, N; j& L+ D- Y - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
, J$ S- d7 m, v h( C' Y
- $collention->update($condition, [
: G' r# a3 E4 t5 x9 _2 J" J: S8 H7 z. b% D - '$set' => $values
4 i3 h( t; }: R$ D7 B3 O - ,[9 l4 F& j7 r+ k, Y1 D* p0 V
- 'multiple' => true//多条,单条false
5 L) S* z4 s) L4 Q& }- g" F - ]);
复制代码- $collection->updateOne(
8 c! K' K1 i! ~ - ['state' => 'ny'],
, t, D; k$ B5 ^ - ['$set' => ['country' => 'us']]* k( G/ }9 {- G8 F w3 L3 U
- );
7 F+ n5 }! S6 d - $updateResult = $collection->updateMany(
( y8 x4 Y1 w! J! M4 p' g - ['state' => 'ny'],, T, A ~" C+ Q8 X; V* _
- ['$set' => ['country' => 'us']]
7 E( Q- h. {2 ^- a% r" d - );" g( t. b/ N& ~; L8 a
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
2 F- w4 i; ?6 s5 J( ?. A; T
- $cursor = $collection->find($condition, [
+ @& _& S! |8 V5 w' C: t# D - 'name' => true//指定字段1 i8 ^4 d- w7 F& J: ?
- ]);7 q# |% i$ G7 ? H- ~! X
- $cursor->skip(5);
0 P$ S: l) ?: k: a - $cursor->limit(5);
. ?7 L1 z& h9 y; ?+ j4 ?6 z& z/ a - $cursor->sort([0 `& F* {' i& m; d$ o
- 'time' => -1# V1 s) W1 R+ q
- ]);
复制代码- 新
/ [8 M% e) x6 e: V* H+ ^
- $cursor = $collection->find($condition, [: m$ |) J( b0 w0 \, F y: W
- 'skip' => 5,
* D' Q# B+ y9 W+ }* ]# U - 'limit' => 5,
" k$ E9 n7 U9 v/ A) Q2 o - 'sort' => [# S% J- l4 d! H6 q5 ?, S
- 'time' => -1; m' G7 j% t' R: U( e' i- A v6 l
- ],//排序8 q# k; u& u3 q+ W
- 'projection' => [
, a4 f* r, T( N. A6 Y( H! b - 'name' => 1//指定字段' t. y% a, b% s3 D8 Z
- ]
2 t8 f$ w+ C1 l7 G+ p: A4 n. G; d - ]);
复制代码 5.删除- $collention->remove($condition, [$ K7 V5 r8 A! i6 E# I( a
- 'justOne' => false//删单条
4 k P! I# l2 w - ]);
7 Z, [$ y! [6 |1 j* o - $collention->remove([]);//删所有
复制代码- 新8 ^6 I8 c. ^. }8 p {9 }9 K2 p
- $result = $collention->deleteOne($condition, $options);! P! z% Z$ i5 ?7 @
- $collention->deleteMany($condition, $options);& w/ \4 }$ R; m1 n
- * Q, O; Z+ D' m8 O% i1 o
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
/ ^9 {# i3 N& {0 M4 _2 ? - '_id' => $tableName//我在自增表中用其它的表名作主键
6 S6 P& P5 a7 V: K1 J& O, Y - ], [( h, W; L( L. Z3 |
- '$inc' => ['id' => 1]//自增% o2 a8 z: y: X
- ], [- Q* T( S- U, [( o
- '_id' => 0
9 N }5 d+ G2 i/ n9 p y } - ], [
) |3 U3 `4 e2 D6 L - 'new' => 1//返回修改后的结果,默认是修改前的# Q2 D( e9 |) e% b, _, x
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([9 ^2 z9 c+ Y3 Q2 c0 _
- '_id' => $tableName2 r, o6 q: X, O/ e
- ], [! Y' u% I5 T! s; V+ m$ ~2 Y
- '$inc' => ['id' => 1]
2 ~+ F! g1 d3 F) d7 G4 h) u# w0 t) Y - ], [. j. H4 _$ o1 m `8 v
- 'projection' => ['id' => 1],3 z9 O4 |) n" Q$ z
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER- C& K& d9 v; L& \3 p
- ]);
复制代码 $ _# W6 }6 P" X1 a
1 J" R* U z, O5 j+ i5 `
|