使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php) Y# D$ Z& Q8 z' S" R1 R/ ~+ _% ~6 `: ?
: l! E% E- p5 ?3 a9 F- x6 t B/ k- use MongoDB\Driver\Manager;
& t; H/ H( h; l6 p7 C6 O" e - use MongoDB\Driver\BulkWrite;+ ^! k1 G" a8 ?
- use MongoDB\Driver\WriteConcern;; i* f/ r9 x: e+ ~8 N; o. o
- use MongoDB\Driver\Query;. n* v8 k' \2 N
- use MongoDB\Driver\Command;
$ j8 H5 f2 O. p" O) r* T
# O0 z! P7 E- x$ [- class MongoDb {
, B2 S3 T! b! ^7 c - + [! W% `4 A# m9 f- y
- protected $mongodb;3 a* D5 Z% y5 r3 N
- protected $database;5 l2 g+ }; o. L) ]5 j( `9 ]
- protected $collection;2 k5 v$ Y0 j4 l- \0 N9 x' P4 d
- protected $bulk;
( o9 L, H) ~0 Z% F/ b - protected $writeConcern;8 z3 _7 I* _: s6 f' Z; R0 ]
- protected $defaultConfig
; e; P% {# F+ w8 L# C5 T1 G8 }* Q - = [
7 U, o. c& d) B- { - 'hostname' => 'localhost',
& q+ V3 E- q1 v; W0 D# U" P - 'port' => '27017',
. d' V; Y& I+ [7 z - 'username' => '',
& V0 d9 a; Z* D0 A - 'password' => '',
5 e5 m( {$ n6 N/ [' {; o" r- u - 'database' => 'test'
) A) ]3 j6 Q" B% Z( i - ];* M/ F) c s( t% y* j6 z; n
3 E4 r1 C$ ?- Q! q D- public function __construct($config) {
& }1 Y+ w, K; ?1 z& R7 a - $config = array_merge($this->defaultConfig, $config);
6 x% h1 w* @2 Z1 l0 S+ V - $mongoServer = "mongodb://";' b' k& j! l3 ^& m5 V3 ^+ z, Y3 _
- if ($config['username']) {) y# D5 V+ {" b, _7 x, M
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';# W! J% s( n6 K
- }' H* I5 ~3 z, Q
- $mongoServer .= $config['hostname'];
% B2 q+ a/ l, t4 l" W4 B - if ($config['port']) {
5 M( K4 ^1 l/ T3 { - $mongoServer .= ':' . $config['port'];
; Y8 h8 {! i2 _3 j+ V3 S - }
5 N- ]- E7 h7 [' t7 j% m9 [ - $mongoServer .= '/' . $config['database'];6 ^. B$ \( S$ S
1 q- ^6 [% U+ u* z- $this->mongodb = new Manager($mongoServer);
5 s. {$ D2 D1 m, t. w - $this->database = $config['database'];
; T `2 s- Q* g - $this->collection = $config['collection'];0 \& u. V; ?3 N, N$ o. R
- $this->bulk = new BulkWrite();& ?; M0 g, w; y. a7 n* ~
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);8 D2 B" b2 P5 I& u+ s
- }" V" G% V0 K& w* L' Z Y: x/ @
- N T0 y, y) M1 ]- public function query($where = [], $option = []) {
- G0 F# F" G: @' {$ i) E - $query = new Query($where, $option);4 X! W: i3 P+ H. S. h# \* o L
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
# W+ R8 V# t7 o [- W* ~ - 9 a' s8 w! L! p. B! ]
- return json_encode($result);8 O- b$ j2 o9 z
- }
d+ f1 c) H* n: d - 7 @1 n5 L( c- i" a* `
- public function count($where = []) {
# S* z& c a, I& u/ y5 O - $command = new Command(['count' => $this->collection, 'query' => $where]);1 o! t: B* [! {: d: m) s; P
- $result = $this->mongodb->executeCommand($this->database, $command);
) k- W( t: \: s" u* S! t6 E1 q/ V m - $res = $result->toArray();/ j- n. x2 R, ^2 g( F% z
- $count = 0;( ~. N4 g9 f2 J! B! Q# n
- if ($res) {! A7 y1 r' V8 N
- $count = $res[0]->n;) |& _% H6 M! S5 L) b1 s
- }3 f8 N* I- J; H! _( b. o3 T' x. a
- V) q& O, ] \- ]
- return $count;
* Y) O6 s+ S' E- g - }
) q: a) c, _/ J8 F) y* b4 p! D0 i
9 v5 `6 e+ N: {8 ]/ {- public function update($where = [], $update = [], $upsert = false) {( a6 }' }5 p3 z8 H9 ]8 n; H5 V
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);' p. R' e5 j! G6 T9 ^: C
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. ^* Z+ G$ |- K; A9 K4 R8 ~ - ) @ ~2 `3 x; I. a- F
- return $result->getModifiedCount();
} h* M2 w# X! ~/ l2 J% }& e6 R - }
4 ]# |/ I+ \- c4 R# ^7 F - * b q, [4 I" K3 C C" J
- public function insert($data = []) {
2 l3 Q: u! t/ H6 n - $this->bulk->insert($data);: o" i$ \- D5 Q0 O
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! o7 J2 @, q, `
- 0 `) H( P5 Z- |0 t) t$ U- D
- return $result->getInsertedCount();
1 Z- x* _8 ~2 r5 @$ I; i - }
' ]4 f2 w6 g {" q. Z% w8 u+ y. K - 1 k" w' k2 B' T* x9 r/ r& b
- public function delete($where = [], $limit = 1) {" ~6 `; t6 q# K
- $this->bulk->delete($where, ['limit' => $limit]);7 O$ x I- ]0 U5 Q2 z2 j# z
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. A/ d3 H8 Z0 Y( b" Z9 Q8 e5 G/ z
$ l" w7 G2 X( l& k# c& f; E- return $result->getDeletedCount();
; Z5 ]4 C2 U/ Z2 Q; G. V - }
% H# r, B. m& e/ x - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
1 n: A: R6 s, P& M4 U3 T
- 新
/ d( K5 O& b1 T# w9 T( e, E 2.新增- $collention->insert($array, $options);
复制代码- 新8 Y L! L% b/ F1 `* f6 r. V/ W _
- $resultOne = $collention->insertOne($array, $options);//单( ]& e! e' C1 Y4 a1 S6 E- W2 Z9 ?
- $lastId = $resultOne->getInsertedId();3 M1 ^% J: P: R
- $resultMany = $collention->insertMany($array, $options);//多# t' B4 B" {5 W8 H( |
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
. L5 @! I. x' |9 d7 W+ D0 `! K9 f
- $collention->update($condition, [
, ?' Q- ^ Q) @ - '$set' => $values+ O9 b. S+ s9 d
- ,[
+ ~3 |6 U" }" p# V - 'multiple' => true//多条,单条false
% D- @* u# g& _ - ]);
复制代码- 新2 }# n! H |* P2 E0 A- [ u
- $collection->updateOne(: H: Q; o' {3 |2 [1 H! F* Q
- ['state' => 'ny'],. f+ |6 _+ E0 M; F3 e2 e9 z
- ['$set' => ['country' => 'us']]# \5 ^, V! g) c; c8 G
- );
+ q X/ V2 s& w0 ?" x - $updateResult = $collection->updateMany(2 d a1 o4 m* F U: z3 k
- ['state' => 'ny'],
}% d& ]% p+ g6 H7 ?+ t! M, s3 i$ I - ['$set' => ['country' => 'us']]7 P: Q/ C" h3 v; T
- );" M& `3 S2 T9 E G2 u9 _9 }2 y8 \
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
# o, r( {$ b/ P7 W! H/ Z) l4 B
- $cursor = $collection->find($condition, [/ b4 {, o- \. E2 X3 H" A8 o
- 'name' => true//指定字段
+ N. o* o$ Z$ H* r* L u/ Z# k# [ - ]);
( O) s1 T1 R( X% I! U3 H/ u - $cursor->skip(5);- L$ _: R$ V; V, o
- $cursor->limit(5);
3 t* `8 Z) e& V- z - $cursor->sort([! A8 g6 P4 `+ s/ T* q2 _1 e. g
- 'time' => -1
) ^: H3 t2 F" k; ]- [6 S& E - ]);
复制代码- 新, f7 S' O2 g" \# w5 z: A; c6 [* E
- $cursor = $collection->find($condition, [
8 d5 A/ G7 L7 p7 N - 'skip' => 5,
- ~4 N; I+ B. |* L3 d - 'limit' => 5,
/ |3 R% K }' L+ l! E* U2 Z6 M - 'sort' => [
4 @0 Z4 w4 C& i - 'time' => -1
\; x$ }$ @' m6 j( X - ],//排序5 k3 }7 n: q( p2 \
- 'projection' => [$ N4 X" k/ H8 @6 K: K1 N/ Q- b2 i
- 'name' => 1//指定字段
0 S9 q( O' Z. A8 G - ]. d1 K7 S; T( |3 h! l. S. v2 `
- ]);
复制代码 5.删除- $collention->remove($condition, [+ O* j1 K' H! u
- 'justOne' => false//删单条+ T( _/ f- g- m: j
- ]);
9 e) ^% N3 H* J" v - $collention->remove([]);//删所有
复制代码- 新
! D$ z4 A6 E1 l$ a% e# x. Z# ~+ {3 j
- $result = $collention->deleteOne($condition, $options);
I" q! n7 Y0 { g, h - $collention->deleteMany($condition, $options);7 `) C/ [' L8 c2 }
- , i: E8 D1 n* A5 H% @
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
) m7 b& X- W- l5 V* Z - '_id' => $tableName//我在自增表中用其它的表名作主键
# U* |+ M5 p! |; ^ h6 D! \ - ], [. z( U! [* h. ^8 i: n
- '$inc' => ['id' => 1]//自增
8 t; N$ p% j2 O# K - ], [: E6 A/ M/ V7 j @ }+ a8 ]
- '_id' => 0: { H, U1 T3 v! Y
- ], [
* W2 h9 G1 N8 G1 r0 X' e/ Z - 'new' => 1//返回修改后的结果,默认是修改前的
6 _' Y! G; G0 D% @" q, I$ D8 k0 O - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([+ k0 W: w' w7 b6 ]* R
- '_id' => $tableName( P7 m# C$ z; H, V4 {7 b( F! ^
- ], [; M5 |9 D3 Z% T# z, l; i c" w
- '$inc' => ['id' => 1]
$ C7 L% c4 P8 h7 y - ], [
5 H& [" C+ ]3 K; Z7 }% A: e - 'projection' => ['id' => 1],. P _' h1 \1 I0 b. v- X
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER! A2 A# d$ ^+ d& V1 F( x! l
- ]);
复制代码 , E% z9 B3 O9 o
* c: `" A5 a6 m4 t! b9 X+ x! l9 F, k
|