使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
% l3 o1 S" M5 w5 M& I - * N! ^+ e( j7 Y- B6 i9 e
- use MongoDB\Driver\Manager;
?- G' @ F" y0 p - use MongoDB\Driver\BulkWrite;& x) ?4 S* O$ g3 f% W. A
- use MongoDB\Driver\WriteConcern;
8 Y' p/ S5 w# L - use MongoDB\Driver\Query;
) U# n8 {9 b) f9 P! T9 z( q" a - use MongoDB\Driver\Command;' q$ x! o6 ^3 w/ A- e% Q: I; c% T5 E
; d4 P* d) `$ ?. @9 F- class MongoDb {
* i! k* @8 N1 c) F6 H% I1 X( T - 0 L2 H$ ]% q; P; G2 L
- protected $mongodb;; G( O$ l/ e- @% M) m
- protected $database;
4 ~2 F. J- Q+ ^% \( ^& j* V3 n - protected $collection;3 n4 H1 R/ \4 B# Z
- protected $bulk;
- F( z; J' s: X# J; ^5 B1 j - protected $writeConcern;
C' ?4 l; s7 O; H$ } - protected $defaultConfig0 P+ Q$ r6 ]5 b
- = [ K" R5 T% S. I' ]* V u: @2 f
- 'hostname' => 'localhost',
1 m3 R* O/ t0 _7 g' b( e - 'port' => '27017',5 J/ b; @1 R2 Q
- 'username' => '',) s8 a% `0 |6 C/ q- S* |
- 'password' => '',# D; n, m$ F- n' a3 u* T6 g
- 'database' => 'test'/ e6 T) O- M' c
- ];
9 S6 |9 @' J$ T$ S
1 X& H1 ? Q7 i- c- public function __construct($config) {
; w' N+ g" G& q7 u1 D+ @ - $config = array_merge($this->defaultConfig, $config);- ?& N9 N8 |, E, K; j$ }+ t
- $mongoServer = "mongodb://";
- g4 i2 ^& P9 P" N3 R3 f J - if ($config['username']) {: z" i' V/ L: i8 I$ Y
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@'; w5 D: U% U) k" B
- }
7 a2 |3 M: `1 a e8 d4 G( J - $mongoServer .= $config['hostname'];
/ k- g8 B+ ?% L D' U' p: W - if ($config['port']) {( s* o3 x/ M% m+ S" E, L
- $mongoServer .= ':' . $config['port'];% \- @- i9 m [ f$ O
- }
9 Z1 H" X: l( _5 P5 Y - $mongoServer .= '/' . $config['database'];' o7 X [' ?0 f5 V* s) _) q8 G
) H }: B3 }- I7 }+ m- $this->mongodb = new Manager($mongoServer);
/ w' B( F+ Q. i6 W - $this->database = $config['database'];
: m; {0 \- v) A p - $this->collection = $config['collection'];7 Q% E0 s/ h& m7 K H
- $this->bulk = new BulkWrite();. W2 [: O! z& ]9 B
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
" U, ~: J0 o4 a& f7 p( B; ` - }
, l* m7 D* Q- }
3 s& D: G [5 }9 f- public function query($where = [], $option = []) {8 w' A0 @+ |2 P" n
- $query = new Query($where, $option);
6 Y7 m7 [; _3 ~. T- t" I4 } - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
) M8 q. ~/ l8 u - 1 Y0 D& f; C* \: [
- return json_encode($result);
* l x0 T Z5 ^! A - }0 x( D; ]5 m( |# `
4 i7 b3 G( C5 l- public function count($where = []) {
i0 w) N$ ^. M! m7 q, S - $command = new Command(['count' => $this->collection, 'query' => $where]);# O; f9 r9 M, Y" \
- $result = $this->mongodb->executeCommand($this->database, $command);
! p: P3 l3 U y" y8 f+ ?! z - $res = $result->toArray();
- X" }7 O$ f) m% Z; j - $count = 0;. |4 H1 X0 V4 ^3 K2 ?% c" C2 [3 H# o
- if ($res) {# w/ m7 E& m! b, L6 [7 E {
- $count = $res[0]->n;
1 D7 n) x2 O1 M& Q1 m - }
# d7 X7 f- ^4 B* l2 d - & Q) ^" X4 _( z: n0 F( B
- return $count;) y: _' [/ h, J( c/ { N U
- }
' G: {% H+ z% u. o& ]$ ^ - 3 e7 P$ @4 A( q8 T0 @! H% N8 A
- public function update($where = [], $update = [], $upsert = false) {
- A1 d6 F& ~! h4 }" o - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);; ^& d7 P7 b7 o7 s2 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. w/ ]4 Z& v1 ^, i% e - % L: u' l; P# w; g( C( N9 J* R
- return $result->getModifiedCount();
5 n4 h j& E6 U0 C/ F5 a' a# s m' w - }3 L2 r2 W+ L* V9 P, T
- - L! s$ V2 {# j2 Q
- public function insert($data = []) {
3 H1 i$ y" t6 S3 N - $this->bulk->insert($data);
: [' }+ n* N2 z5 A; y0 } - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
2 m/ \+ k) C. ^) f - + u; L d& ~. D' | O; a7 p
- return $result->getInsertedCount();5 ~7 q1 D, ^! y0 E# o& c
- }
B, K3 c* w3 E
8 d+ X- Q7 R, v% G- public function delete($where = [], $limit = 1) {7 Y W4 e- m7 Y0 V
- $this->bulk->delete($where, ['limit' => $limit]);
/ C: k0 v- }/ C, w! I - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' |( R; I1 F: C1 T; T! Z( f( q, Z
8 w! @" ]/ x$ T( f1 `+ k9 B1 z- return $result->getDeletedCount();
1 y- [& h! o, g! k* p - }
& J/ F: @" K$ k' [. d - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单! G/ N$ ^; Z7 z( N
- $lastId = $resultOne->getInsertedId();
' g/ n- B, I Q( r2 [ - $resultMany = $collention->insertMany($array, $options);//多
% v& U0 t0 c. K- a: l. {, H - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原1 M: R$ k$ e Z% ? m n4 u5 d( x
- $collention->update($condition, [3 ?1 E, V6 h8 Y: K
- '$set' => $values! `. x& F' O$ V: D. H
- ,[5 N' {5 r; D+ d' u, q' I6 y, E
- 'multiple' => true//多条,单条false
0 C0 Y U/ j- b& \- ~ - ]);
复制代码- $collection->updateOne(6 r+ Q$ I Z: ]% |6 A
- ['state' => 'ny'],
8 i7 F* ]! ~# |. w9 Q - ['$set' => ['country' => 'us']]; V9 t' H* e8 `8 o) X
- );
: G8 C5 |) s0 E% N; z - $updateResult = $collection->updateMany(
L4 W, ]7 e* q1 m: U" l - ['state' => 'ny'],
! h: a, h& j, y0 `6 e - ['$set' => ['country' => 'us']] _6 m; p8 M5 J& x6 L8 ?7 M
- );, e" |# K; ]7 u- V6 O! E2 S
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
7 h* c# G2 W" K7 v4 ]) H - 'name' => true//指定字段
3 M# x! e0 Z* s - ]);
/ h d, F4 p) a- H - $cursor->skip(5);' I2 x2 R" R! E. E: z
- $cursor->limit(5);
& `" Z$ i3 V x; A3 \ - $cursor->sort([6 l I, _! b1 _7 y
- 'time' => -14 j- u, J5 A9 Z$ l: _) p
- ]);
复制代码- 新: O/ ?3 k" W8 u, v% g+ G
- $cursor = $collection->find($condition, [/ Y: U" ]3 m1 \) x
- 'skip' => 5,
; h7 P% @ |8 V! H! H3 r - 'limit' => 5,
5 H+ c; n7 j( i9 `% C: v( H T - 'sort' => [
# M7 i. q- q; T* @3 }- g y - 'time' => -1
/ }/ C1 a% i4 s/ i7 L - ],//排序# K+ g9 W+ h1 w5 }+ {/ k8 R4 {
- 'projection' => [$ Z8 h# {( S3 [8 i6 t% z4 W& `2 j3 e
- 'name' => 1//指定字段
! A1 V2 e: l2 k/ O0 S - ]
2 B" a. M) r* I* U2 O/ ^' E* j; } - ]);
复制代码 5.删除- 原
; k' t2 i) v0 m6 K, Y0 X/ i. ~
- $collention->remove($condition, [9 k- P% M) ^ m- T3 S3 |, ?0 U
- 'justOne' => false//删单条
5 n0 W% Z' U N7 _* e - ]);3 [$ {/ q6 W5 W' G( n- |$ N+ Y2 f+ b
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
* ]5 J! _( p1 Y7 E - $collention->deleteMany($condition, $options);
0 ]" ]( I8 i3 F! Z - 2 [' t3 J5 D! P6 w1 U5 w# y
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([5 Z( y& @" ]0 K
- '_id' => $tableName//我在自增表中用其它的表名作主键
% ~9 U: R' G' v - ], [
8 c% D, A6 y) r2 w4 r - '$inc' => ['id' => 1]//自增
+ c. c2 D$ k, e$ { - ], [
+ t$ Z. T$ y1 ^* X# C6 p - '_id' => 0
+ z, M; O2 X+ U+ [: f - ], [
' X! r! M( A3 |; j u, y* g - 'new' => 1//返回修改后的结果,默认是修改前的9 l- f6 f( \7 l3 c" [
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([: k( c" F4 H3 N6 z& {
- '_id' => $tableName, _- d, l9 Z: T [
- ], [+ d, Y% M* S5 j( ~9 ?8 {3 j
- '$inc' => ['id' => 1]8 ]/ ]+ ^! n; T. `4 I( Z
- ], [
0 }# Q: V. {1 J9 q5 G - 'projection' => ['id' => 1],
7 H) Y/ l4 ^ A2 o" w3 S4 O - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER3 C% P1 [1 ^/ P: x( _ n
- ]);
复制代码 # C. h( v$ Y+ j
/ y# q* P- ~: [) `: D# G8 V' \' W3 t |