使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
, T7 A1 m2 ?" U; `$ ]5 s - # M4 u4 q& @' D
- use MongoDB\Driver\Manager;
r' c7 B; \+ d$ p0 ^; e4 }! E - use MongoDB\Driver\BulkWrite;
9 k! h% M0 t0 P+ P6 c# y - use MongoDB\Driver\WriteConcern;# j& f, b( {" c( L
- use MongoDB\Driver\Query;
- q& a1 E r, T* D8 r8 e0 x1 X - use MongoDB\Driver\Command;: o7 J" ]# w- c4 A
, h& g; s- v7 @, h- class MongoDb {1 i, o1 W% L5 T: z
- * ]- \, l9 Y; V, e& @/ s
- protected $mongodb;: m' }" f4 W7 J9 h
- protected $database;/ T9 f G7 `& Z
- protected $collection;$ Z S+ V4 `$ Y" Y" w8 i
- protected $bulk;
5 s9 K& @: ~5 b+ u; Q - protected $writeConcern;
; Z3 `* G8 R2 Z - protected $defaultConfig1 x' x7 Q3 g( D4 h5 G% O+ S
- = [
/ h8 _9 S7 E: {5 i% y# L - 'hostname' => 'localhost',
6 ^) l: X+ n, Q( O1 W9 @ - 'port' => '27017',
0 e% E i, o/ H2 H - 'username' => '',1 I: m+ i; \/ D( }
- 'password' => '',& o' v7 `- t" r8 z
- 'database' => 'test'' L! h% D% e8 ?
- ];+ c5 d$ t& \0 x# P* h& H
- , i1 c: L/ f+ b' m/ u# ~
- public function __construct($config) {
0 l& Z% Z5 T4 Y0 L9 a( C; `0 o0 m9 c - $config = array_merge($this->defaultConfig, $config);* ` O$ s4 ?/ {) }( q& ^" j
- $mongoServer = "mongodb://";. i8 a' u2 d7 ~7 e2 f
- if ($config['username']) {
1 t' f& u6 B* {* ^" D - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';1 N1 V; @ X6 S& a) z
- }, a- }5 j7 m6 Y, f
- $mongoServer .= $config['hostname'];( d" z4 `/ o# b+ k+ k
- if ($config['port']) {
( X) ?3 `3 s6 R9 E+ S' d - $mongoServer .= ':' . $config['port'];# v0 j' u; P B# B1 y [/ K
- }" }! j6 [" A% R7 F4 x S
- $mongoServer .= '/' . $config['database'];8 n, ~' T0 E2 `; ^$ W: i/ _
- ; o: z U; |% ~' I5 I
- $this->mongodb = new Manager($mongoServer);) n: O! O; \9 I0 e2 C
- $this->database = $config['database'];
4 y/ C. |3 b2 { - $this->collection = $config['collection'];
" u( Q' w& `6 H) X1 V# Z - $this->bulk = new BulkWrite();
$ f' U' K# L1 T/ `. I) D3 S$ ` - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100); @0 I# S6 L+ d# K& v$ q
- } P2 r: Y) i! v3 S/ r/ i# m0 S
- 0 D9 Y& ]' o% s, Q! O
- public function query($where = [], $option = []) {' Z% }6 Q. V0 [' {) i
- $query = new Query($where, $option);
$ @( D. Q% X5 B0 v" K - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
o0 Z6 t# a/ d* {+ D - + o1 U# N3 A; w* c, C- h! [
- return json_encode($result);
2 o, j0 @* v1 R( y - }
) H3 ]3 z/ P5 }/ H7 Y4 j - ! v+ w$ u9 h8 l F# w
- public function count($where = []) { `. J) J0 W! \# c
- $command = new Command(['count' => $this->collection, 'query' => $where]);
0 }+ v! ^: Q5 ~9 ^: C; i" \ - $result = $this->mongodb->executeCommand($this->database, $command);0 W( F8 b7 M5 {% Q$ R; \
- $res = $result->toArray();) j' j/ g E m z
- $count = 0;
9 N' c. C+ w. t; k# s - if ($res) {
- ?' v- p9 `' x5 i8 P2 n$ E+ q - $count = $res[0]->n;* Y& P# `; b( l, F6 o
- }; m6 Y R. T1 I- n6 F9 z3 C+ Y, q
( w+ X2 Y5 D" ^3 L# {' `) h- return $count;0 A- n: f! O' B; K
- }% W& L' z. e5 F; W* Z( n
- 2 S% A& I' S- ]& `# h$ x1 q
- public function update($where = [], $update = [], $upsert = false) {
. W* h9 W5 G# v5 g1 v - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
; H. T( B) X& d6 Y# }6 Q - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);; H$ _' t' u* Q* s& s9 u, t2 N
- 6 a+ R4 p. E/ _$ J7 @, p
- return $result->getModifiedCount();$ e: C' ]+ T1 g; ?- S" n
- }/ h: \! Z5 N, ]; A3 T
- K0 J. t" T r/ w
- public function insert($data = []) {) v- m0 o5 H' M! K* w
- $this->bulk->insert($data);
- I! y* q+ _& g) Q; H - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 j6 M4 r4 [! k( E/ ~7 |9 A3 L/ W$ \
; R# e F( M- L0 f. m. T- return $result->getInsertedCount();- z/ v2 X! @& ~ l y
- }
/ L, C+ R- \7 I, }- Q% {
: _/ J* v9 O+ o3 ^/ Y- public function delete($where = [], $limit = 1) {
5 ~( ?8 b5 T$ p4 V7 X8 u7 H - $this->bulk->delete($where, ['limit' => $limit]);8 }* Q9 [- [& I
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
& ?8 Y/ ]* f t2 y* _) G- j! Z
: K' |3 Z0 i6 @ M- return $result->getDeletedCount();
( }( E7 U- u6 T# _1 g! k2 O. | - }
5 [7 _6 }1 f- E8 t - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原) g I0 R0 A! x' j' i( _: i5 }- d
- $collention->insert($array, $options);
复制代码- 新
* d6 C; G0 W4 u0 i i6 N
- $resultOne = $collention->insertOne($array, $options);//单# C$ ?3 i D! k7 `- Q
- $lastId = $resultOne->getInsertedId();
1 R" x& D6 E: d7 m! R9 {* j; ] - $resultMany = $collention->insertMany($array, $options);//多
+ {7 O) m: x# d& \" k+ u2 @ - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原* f' c" Z* |2 ?* @. o+ S
- $collention->update($condition, [. h- l, l Y! I" P$ s
- '$set' => $values4 j9 r& ^0 ^# k, u7 }
- ,[4 B; E9 N4 k" `2 R3 n. Y( G
- 'multiple' => true//多条,单条false
: [' D' U' K8 S' z- {0 A - ]);
复制代码- $collection->updateOne() x; v6 M/ W6 W+ _1 S* h
- ['state' => 'ny'],
: z& P3 A5 f2 p# {1 \ - ['$set' => ['country' => 'us']]1 I0 }' ?1 o5 ~3 W- @- @- L$ F
- );
( j, Z5 v( [/ ]2 n* L- Z( E) O - $updateResult = $collection->updateMany(
. |( ^7 H+ b$ j' d+ | - ['state' => 'ny'],7 B' Q9 a$ Z. F4 S
- ['$set' => ['country' => 'us']]
8 b# M$ N0 g& `- | i3 _ - );
( V9 M# ]8 C( M1 N - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
3 G! Q/ p2 A- H0 h. U- f
- $cursor = $collection->find($condition, [6 Q4 Q" y/ G a; r5 v. g
- 'name' => true//指定字段* O8 m$ N" Q9 y) k7 Q# Z! ^
- ]);; u& b, t, @, F! X j$ c3 ]
- $cursor->skip(5);$ p! Z u3 K' W3 D+ N* [
- $cursor->limit(5);
6 M" l) t2 r, V. C9 `6 J$ i8 P - $cursor->sort([
: q+ [% T9 Z* Z2 L2 T" D% { - 'time' => -1
1 ?8 J3 N2 V1 Z) f: X6 C - ]);
复制代码- 新
6 t# i1 }, ?8 E2 D, K5 _, u
- $cursor = $collection->find($condition, [4 }& s7 z: ^, B4 u4 u
- 'skip' => 5,1 r6 E4 S+ b/ I, t* d; h
- 'limit' => 5,
* `0 _ C! M( N" U& j - 'sort' => [
% j i3 M$ ?% L - 'time' => -14 W O$ r' g; s9 ?, f
- ],//排序! O! o ]; B+ j1 `$ I9 C I6 W
- 'projection' => [( _6 f. c. N, l+ s' `
- 'name' => 1//指定字段
1 {" c/ t" F$ d9 | F2 A6 _6 ~$ f - ]7 v1 _0 h$ j- i3 \; Z s5 F
- ]);
复制代码 5.删除- $collention->remove($condition, [
) c5 \" H+ y- h; d* S% A7 W - 'justOne' => false//删单条
8 p4 D- e5 r" P; n6 z: A6 O5 D - ]);3 Z% m F) N( D( G; e
- $collention->remove([]);//删所有
复制代码- 新5 M* g9 B/ y, i- d2 i- d; ^ @
- $result = $collention->deleteOne($condition, $options);) K: G$ w% v# f! Z" T5 @
- $collention->deleteMany($condition, $options);# N0 H7 N: \* H' v& B+ l
1 b: g- L! C+ \- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([7 G0 W0 g' k2 @: N1 G; h
- '_id' => $tableName//我在自增表中用其它的表名作主键
6 j5 j. }; m+ R1 _' W1 W1 q - ], [" p, {2 T: U9 P; h
- '$inc' => ['id' => 1]//自增
( L# _" t$ b# N# ~3 o - ], [9 k4 I( h' L3 C0 L) X
- '_id' => 0, s8 V* S* y" L8 X+ @3 Q0 d, i
- ], [
' L# w+ \- X: A9 m8 i' e - 'new' => 1//返回修改后的结果,默认是修改前的
1 k* J: G- {9 N5 V - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([0 [; d" g7 m" K" S
- '_id' => $tableName
4 ~, @" B' i. ]3 U7 i - ], [5 L% R$ Z8 Y0 p6 M! d. L& I
- '$inc' => ['id' => 1]4 g" ^& {' R, }# q( s
- ], [ y- W& I; N7 v/ U
- 'projection' => ['id' => 1],& A9 }" I! K' y ^$ N2 c
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER" m& ~5 E+ M2 `' M
- ]);
复制代码 0 D3 i1 e6 o. `/ V4 |& p/ c
( t% \: `2 E- I+ g [0 G4 ~9 t
|