|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
0 e+ a. t3 {) P. h u* U9 U7 N; {1 N; q, E - 8 B( s' u4 ]- j1 z6 C& H: ]5 }: @
- use MongoDB\Driver\Manager;8 O; ~9 G/ J8 |+ q4 p9 q
- use MongoDB\Driver\BulkWrite;8 t- n; ^) q, d% t$ o
- use MongoDB\Driver\WriteConcern;1 V9 l( e: K' ^# M7 w1 G9 a- ~% b
- use MongoDB\Driver\Query;" d5 r7 C: H( h; _; d V
- use MongoDB\Driver\Command;1 e. t# q& \6 A% `* q" ]# l- y
: `# C% G, c# F G- class MongoDb {
1 [+ M4 E5 {5 w( J' `9 i1 l( u
: w4 ~" \8 b, Z- protected $mongodb;* H# S/ X8 B. O- N
- protected $database;& i' S! l+ I1 z' R! i6 |3 ?& I
- protected $collection;; M& ~: v% ^: v0 A4 b9 {; R
- protected $bulk;
( Q6 U+ t9 g; I+ }. t - protected $writeConcern;
; o. r, ~# Z+ O# P7 q - protected $defaultConfig0 |1 X, {7 e+ B* `; ^2 v* p2 u+ a7 X
- = [* L( P5 g7 [2 V4 s( @% z5 C+ U* L
- 'hostname' => 'localhost',( @) O h' ^" E5 w* P+ y* C# |
- 'port' => '27017',4 l: E: U% [ t2 |
- 'username' => '',5 z2 i+ [' q% H' q5 Z
- 'password' => '',
5 o1 e1 i5 \# I- @7 z$ } - 'database' => 'test' o9 I6 V$ d0 L* S+ k% X1 ^1 r
- ];
" F. ^% ]3 S' M+ f
: K6 ^% }- L2 p6 d' h- public function __construct($config) {3 d$ o0 j/ ~# \& t9 z5 u7 T' B
- $config = array_merge($this->defaultConfig, $config);
7 p" D* h+ Y+ G3 y% N# y; u7 T - $mongoServer = "mongodb://";
7 K9 ~: ]! x+ \0 U& @ - if ($config['username']) {
8 }& [; ]% e$ m% b! x - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';# K" y% G' h- r {( F9 c% i
- }: I* G o" M& ^0 x+ t, w$ I
- $mongoServer .= $config['hostname'];
, x. T( f2 a7 X; e& u2 v& L - if ($config['port']) {( n7 A0 W |( l/ a+ T) `, o g
- $mongoServer .= ':' . $config['port'];. f8 m$ @3 M, D) `6 |" K
- }/ @0 Y( l! J. r$ v. _6 |. D2 F
- $mongoServer .= '/' . $config['database'];% G( I# n9 s/ B1 K% M, ~0 W4 s
! Z4 \; b/ p2 o% V+ b: H! z! _" e& j* y- $this->mongodb = new Manager($mongoServer);; u, F& O& R# G# F
- $this->database = $config['database'];
+ B4 |2 C+ P' X8 ^# w) ~7 e8 r, N7 L; ^% y - $this->collection = $config['collection'];2 [% E) o$ [) ?8 M( p
- $this->bulk = new BulkWrite();
( S/ J& v1 U( ^, j6 b2 I5 l0 D+ S - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
1 A* B; z( u. E* T/ k" B: G - }3 q0 u# ~- o. }% a
- ; l$ @0 Z: p. }$ r; _9 ~( [) }
- public function query($where = [], $option = []) {$ Q/ `2 U0 I- h; J: C# e
- $query = new Query($where, $option);# N# L* z& R+ F. Y! Q" P! D2 J% P
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);5 _% M- U, e P' v
; K3 x) ?+ O. _- return json_encode($result);6 c- P: {; Y1 m7 j, T% O$ O+ G
- }5 q1 K! P7 I* L0 f6 y$ Q) w k" P
# W* i* U' p6 @/ `5 U- public function count($where = []) {
, A9 }+ s! y4 G5 h9 a - $command = new Command(['count' => $this->collection, 'query' => $where]);
6 I# \" E' L! m7 N) Y- z0 o% G - $result = $this->mongodb->executeCommand($this->database, $command);3 W0 e8 f: H# ?- W
- $res = $result->toArray();# x! n& |$ R% R! W4 Q! `
- $count = 0;4 S/ O) |3 c" Y! p
- if ($res) {
" t7 e" m% ? t, |4 P8 { - $count = $res[0]->n;2 [% s7 |# _1 ]9 j9 e, I0 v' X5 N
- }
2 U2 N; x5 S: j8 P2 R) k - 8 U& I" }7 h5 a1 C+ S, `
- return $count;
' c' y) ]+ k# `# D5 v - }
6 M' i0 g+ @6 g; T - 2 K( d0 S# A) g: Y! f' y( _
- public function update($where = [], $update = [], $upsert = false) {
# n3 I n$ c* p2 s2 [ - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);% w; j! ]- _. L( n
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
4 K8 Y5 l' u2 f- f* P. c
* P; ?. l, h8 |3 s- w/ v- return $result->getModifiedCount();
9 t% U! R0 h& w N! J" ]( @0 L - }% M, }% o9 N# z' m
( P6 y" x! q+ @! N, F- _- public function insert($data = []) {
4 |) }( e- Q) {6 |' G - $this->bulk->insert($data);
9 y& m3 H: t4 I0 ` - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
6 Y+ M- j! Y& Q1 f: }7 D& R/ i$ L - + o0 b1 e! v) l( R8 `, k/ H6 i0 J8 q% d
- return $result->getInsertedCount();
( W! z! ~ ]$ x" V5 D - }3 z$ B+ M' N' S6 j, `8 n
- 6 P( h( J. B2 B+ e' C) \
- public function delete($where = [], $limit = 1) {6 i/ \ Z0 I: f* ?3 t* l9 P, m# Z
- $this->bulk->delete($where, ['limit' => $limit]);! E2 a/ R7 ~: D2 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);, J. t; O9 R+ Y1 I# O f. |
- ' n6 }+ s. u) q# _; f; J
- return $result->getDeletedCount();
9 n. v" N% g* v" \4 p! |- c - }; z0 P" D: c6 ^
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原5 n1 L7 p5 e- c7 D6 W& K- n. ~+ F
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单6 d) \: z! B& s" Q
- $lastId = $resultOne->getInsertedId();
+ D6 q) y- x/ b2 \4 L/ U - $resultMany = $collention->insertMany($array, $options);//多
9 b' U1 \2 ?; X - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
4 U. c7 v+ N3 o' N* d( G+ n+ U
- $collention->update($condition, [
4 Q7 y. F% C2 U& v# `; [; J/ @2 Q - '$set' => $values5 T- }: |8 w' D$ }: N
- ,[
1 I. I. M9 l$ Z" c - 'multiple' => true//多条,单条false
# K! Y" y$ w( D" b7 g/ d - ]);
复制代码- 新
5 H3 [2 c# p S: \6 c; }: l4 K$ `
- $collection->updateOne(
4 _: K L) r+ o2 y1 Y - ['state' => 'ny'],
1 }) R% N( P( d - ['$set' => ['country' => 'us']]
& x) c H0 J* ^0 m$ ?/ U# T+ x) b - );
4 q% Y+ x5 v! }9 Y - $updateResult = $collection->updateMany( x; t. Z/ _& B3 I: H
- ['state' => 'ny'],
' c8 `3 `7 u: D2 ?0 |% i# _ - ['$set' => ['country' => 'us']]% ]" x' ]; Q" U& y- U9 G( h4 I
- );
! ^) V& o+ n$ \" K4 w - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
6 \/ P: W$ h1 S+ N; |/ k" z - 'name' => true//指定字段
0 r- t5 G, j1 I+ `& Z) w7 W - ]);
& c/ v- I& o6 {) ^, B4 ]! } - $cursor->skip(5);6 A1 j% o7 J! ?6 X
- $cursor->limit(5);
: s+ q) H8 X) e7 q - $cursor->sort([$ O2 u d7 A- J
- 'time' => -1
7 g: D! L3 _/ K d4 W - ]);
复制代码- 新
) T/ V* N* V; X0 ~; z! x6 P9 Z
- $cursor = $collection->find($condition, [! F% a) e3 O2 a! M& @8 P0 ?7 |
- 'skip' => 5,
! e/ F9 A5 s/ t9 s( U3 Q - 'limit' => 5,% V7 x) H& E( z, G, [
- 'sort' => [
* C8 y9 O) F9 k& \2 i- w0 ~4 A - 'time' => -1& h$ n, ^( _7 C7 E! B6 z0 ^
- ],//排序
) ~ Z5 a, ?6 k& I7 q - 'projection' => [
8 w$ V3 C& j4 W - 'name' => 1//指定字段- E* X8 y$ B2 {. E- W. Z
- ]
' s+ O5 M! g! ~) @/ H1 C9 B3 j - ]);
复制代码 5.删除- 原+ A, G8 a7 u1 b4 G/ L$ b5 w# v
- $collention->remove($condition, [
* U* z$ ?7 K3 J. B: H - 'justOne' => false//删单条* S7 R( s' p! r( a4 Z& z
- ]);
g/ Q A( y/ S - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);" @5 q8 |8 D: R: H( M# f
- $collention->deleteMany($condition, $options);8 w+ k0 C! u" i8 ~ q8 G
- z/ }! {% H/ S7 L9 r5 P6 \3 B- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([: K8 {8 L Y7 ^ i/ z% h: y- e
- '_id' => $tableName//我在自增表中用其它的表名作主键0 a1 V4 f" c1 h
- ], [' p0 f* l% v, o t$ G, ^
- '$inc' => ['id' => 1]//自增: \7 Z0 F$ B/ N* F2 v) M. h5 x% C
- ], [
6 I7 P5 { ~4 M - '_id' => 0
" F/ P* {6 _% r% _: V( W - ], [
4 N; d& e# a/ [! Z; O8 _/ y - 'new' => 1//返回修改后的结果,默认是修改前的
0 g" L2 m! J% [ - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
" G3 u! I! B5 I: [$ w% [ - '_id' => $tableName) y7 Y/ y. T) b6 ~
- ], [: S# Q: J# `$ |/ ]6 e+ q
- '$inc' => ['id' => 1]1 x+ t$ r# a, p3 m7 ]
- ], [
2 Y; H+ a4 h+ r. L$ t - 'projection' => ['id' => 1],
8 }7 J7 A5 o/ b) x0 f" m ? - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
" i; d* h/ T) z1 ? - ]);
复制代码
; Q; M( F2 J, q( \8 @4 O# r/ P' r1 ^ G+ C/ v" i( Y n( H
|