使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php z4 I) J: y7 T2 }2 D$ H
9 J: M" e# C/ f3 ?( q+ Z- use MongoDB\Driver\Manager;
$ U* q# e2 C/ Y; n. V5 C - use MongoDB\Driver\BulkWrite;
: N0 v% @( `+ x5 _& W8 e1 d/ W$ L" X$ Y - use MongoDB\Driver\WriteConcern;9 `8 n8 Y& x% s- \
- use MongoDB\Driver\Query;
, t0 N1 f' @) D. O( b9 u - use MongoDB\Driver\Command;
2 I( w, r x' e8 F% E" n2 g
) p( g5 l; v+ D+ l! `- class MongoDb {' i; ^5 \+ @' C& {: a& |
/ w" Y" _$ D$ N; h- protected $mongodb;
) ^% Z8 ^5 p4 `! X) x - protected $database;2 Z7 V; w. W. ?$ A, \1 J
- protected $collection;$ m: z7 F9 J; [# P& x* `0 B1 A( J
- protected $bulk;1 h( F& ]3 P0 G. Z; j$ i
- protected $writeConcern;3 G6 W' T3 }# }3 n5 f+ o( u; x1 g
- protected $defaultConfig
" L- H8 }, D0 o/ M - = [1 ]( k% v! g# t# q! E
- 'hostname' => 'localhost',
3 O0 n& M3 g: z3 l3 _/ n - 'port' => '27017',
4 b; D" r/ T: k6 \0 r! X& u - 'username' => '',2 c6 J- `( y, f" Q! o# s
- 'password' => '',
7 P& ]" |+ S6 \6 w4 |" ]8 S: j3 `; P - 'database' => 'test'7 D0 Z- Z& q. R
- ];6 ?: h# E1 L- w- A# `. |
- ( ?! P% b& B) b4 g9 @1 t7 m
- public function __construct($config) {3 h3 Q2 H* u: [* K; x7 C1 |, M
- $config = array_merge($this->defaultConfig, $config);# S, I) f4 T n9 S3 C# S4 G
- $mongoServer = "mongodb://";9 ]- t- J: ^" I A8 d
- if ($config['username']) {6 c% c) ? B4 H# t) R* i
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
q! }. m/ J# ]& C# K1 X: h - }
0 U( H1 O8 W I$ f) M- Y - $mongoServer .= $config['hostname'];! h* o3 Y0 h4 I
- if ($config['port']) {* v W; O9 ^7 t
- $mongoServer .= ':' . $config['port'];
" s( p2 }, W: I8 u& r/ k0 e - }) E; j) x& q1 _+ m5 x! P$ g& s! C
- $mongoServer .= '/' . $config['database'];9 ?& x5 l: m3 @5 Q C8 Q/ u9 A
+ S/ S# c |3 G! I( [: U! Q/ k- $this->mongodb = new Manager($mongoServer);
: e, @7 P Q4 q; p - $this->database = $config['database'];, c+ z* o3 F9 T# C' K& [
- $this->collection = $config['collection'];
* Z: w" L, }3 H& \& n4 T" T - $this->bulk = new BulkWrite();% b& c# o/ j N8 c- A9 G
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);: o3 P8 K! Q) S% K, {% K% P6 a
- }1 Z- ]: M7 H/ U( V/ G* k1 u1 \9 _
6 K2 [# T0 L9 u+ N- public function query($where = [], $option = []) {
$ p6 d9 N1 x* A5 n" k2 w4 D! ~; R - $query = new Query($where, $option);1 X* v- E5 Q, C, I
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
& N% e1 b1 ]; C# G- d5 v# R - 6 h4 ]2 Z$ e5 Q/ V+ C7 [
- return json_encode($result);
P3 x8 k" z/ u9 M6 P$ M - }% e* p8 y2 n O! @2 V+ Z
8 q' f8 H3 N* q# {" V- public function count($where = []) {6 h4 \1 M; B) Z' b3 q C4 R
- $command = new Command(['count' => $this->collection, 'query' => $where]);( _+ P8 F8 h8 H8 i
- $result = $this->mongodb->executeCommand($this->database, $command);
$ \9 [* \& [/ n; {# j - $res = $result->toArray();7 D& P0 Y1 w+ ^6 N& r7 T! K
- $count = 0;
4 i M" b! U# t7 w+ @* C( _ - if ($res) { a! i- i( f% G, ?* c2 q }: e. l! ^
- $count = $res[0]->n;0 `( I, t6 h1 s8 o* s+ i; b
- }9 e4 D! E5 p9 s6 ^' {
- 7 a/ R3 f' \1 ?6 D
- return $count;4 l4 y* r3 W* b
- }
4 V N0 \' f) ] y4 `
1 @. g, V7 L0 \: d" o! x- public function update($where = [], $update = [], $upsert = false) {" G8 D8 S8 o2 F! N) b% v
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
4 H, w# E- u+ i' n4 C4 X( f# X S - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);) `/ I/ M! }, s* K4 p; f
- % I# O7 v" R/ q# i" \4 I; j
- return $result->getModifiedCount();
# n% j, M- J: v( v* A& z - }
* z" r6 S: i; _- t- T
5 N2 V7 P) t9 L: q8 q- public function insert($data = []) {- n5 O' O. K5 f! e; H
- $this->bulk->insert($data);
9 L( @3 P! h2 j6 l3 R - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
; {) V( l* @' V# O; P - 8 m, W* f; p2 J( P
- return $result->getInsertedCount();
$ i, G- Q5 o" C; B - }
}+ D+ @6 t) h3 O* c+ F4 e( l- t, _ - ' D6 V% h, A1 \
- public function delete($where = [], $limit = 1) {2 X$ J) K1 p+ X( I9 Y
- $this->bulk->delete($where, ['limit' => $limit]);3 q9 N5 N( p4 T
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
* c( N8 C1 D6 U
/ W5 K- o- c( F& P- return $result->getDeletedCount();8 \5 q/ |3 b( E/ p$ ~8 N* F/ p
- }$ ~' {& L. F3 w; a) P5 }
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原) R" ?, `, N0 V( k( Z, f, m
- $collention->insert($array, $options);
复制代码- 新
1 n- v8 P& w/ B. U/ y6 Q
- $resultOne = $collention->insertOne($array, $options);//单
" y3 L# n1 o" O! A9 [# r6 _& v - $lastId = $resultOne->getInsertedId();
+ c0 [0 q9 X/ M8 P A$ L - $resultMany = $collention->insertMany($array, $options);//多
4 S/ x+ ?2 W; ~: z: d7 `4 i - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
. Z1 m, i0 q" L1 T; }+ t - '$set' => $values9 n( B9 r, ~4 Z7 r
- ,[
7 Q5 q$ n7 }+ l. T; ~ - 'multiple' => true//多条,单条false* w1 i/ N* u; ~( b1 S7 B
- ]);
复制代码- $collection->updateOne(6 ~! W2 o# T5 f1 d
- ['state' => 'ny'],
5 Y. J* g' C" K' V- [ - ['$set' => ['country' => 'us']]% J D6 L/ Z6 ?, j$ R7 ^
- );) i) T- G0 l: o9 p
- $updateResult = $collection->updateMany(/ B" f8 b- A" h$ u: d& B$ ?: ~
- ['state' => 'ny'],
, C* I3 u/ X8 i8 o' _7 s" y - ['$set' => ['country' => 'us']]
, h1 o5 x0 @. u - );
. Q! q3 z" D, m$ Z1 Z4 V - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原- ]( E- o) L8 |- D& n3 M& _1 q
- $cursor = $collection->find($condition, [
% D$ A1 R$ D9 k0 Q j - 'name' => true//指定字段5 z7 n5 g" N6 z5 D
- ]);
, g. S+ g+ O1 X3 S+ E - $cursor->skip(5);
& X- B+ m' D! |* m, f - $cursor->limit(5);
9 l$ f6 p) M, T - $cursor->sort([
! d; w ^ |5 k5 q7 ? - 'time' => -1! A6 K4 J3 M$ }0 ~
- ]);
复制代码- $cursor = $collection->find($condition, [+ k/ a! k7 N* b7 V: H) G4 l8 V1 _* U0 y- w
- 'skip' => 5,1 Z; @% V* |* d5 I7 E* `6 k; Z; U
- 'limit' => 5,
+ b- Z: A8 }+ C9 @0 `5 S- ~( g - 'sort' => [
: w* e' W, @& Y1 J - 'time' => -1" m* V: ~! w! s$ i
- ],//排序7 X Z0 [/ y: c. q8 d! t6 {
- 'projection' => [
5 Y" M3 q, G- a2 ~5 w - 'name' => 1//指定字段
& y% n; R- C5 s1 l( L6 c) U - ]
1 Y2 U. M4 q$ p4 E - ]);
复制代码 5.删除- $collention->remove($condition, [
, A& n: a. W0 l - 'justOne' => false//删单条3 Q1 G- l% i, f* C9 v$ x
- ]);0 G% f. V; S0 e; f
- $collention->remove([]);//删所有
复制代码- 新
$ I3 J/ n2 W' d$ k0 h1 z# ]$ F5 O- d
- $result = $collention->deleteOne($condition, $options);
6 P4 e9 r- I/ R! J$ a& c - $collention->deleteMany($condition, $options);
+ p* \( t6 S- _ - 2 v4 _, u/ o1 P: ^
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
6 K, B$ }4 v& V, N: Q! B! |& k& G - '_id' => $tableName//我在自增表中用其它的表名作主键' O7 ]5 \2 a4 G4 \
- ], [7 U3 }' R- s! R7 o$ V' X* i
- '$inc' => ['id' => 1]//自增4 @6 N& B+ o- V; |: j
- ], [
% n, p( V) `; `+ B0 F - '_id' => 0
: R0 I& p4 `0 ]2 _, I - ], [
& J6 W+ {# m( o" d - 'new' => 1//返回修改后的结果,默认是修改前的
! v* }) w- k$ o0 Y, ~; V7 _( h, ] - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
! g! X! }. h7 \7 Z) b) t - '_id' => $tableName
! y) B: W8 R& ^8 m2 [/ j+ B - ], [6 f2 |, ?' O* x. ]9 q: M
- '$inc' => ['id' => 1]
7 i" h; B: k9 K) L, h - ], [6 ~8 C/ }2 E* R8 M8 D @: U
- 'projection' => ['id' => 1],; r) B& k+ Y% a4 I& A! x
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
) n$ |/ @1 \! @& A - ]);
复制代码 1 e1 w! k7 e6 a1 _, e! a
( S, M3 X9 n& C6 ]$ V |