使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
D! G& _3 v7 T1 Q. ]# E
7 G' g2 K: Q3 |6 h* h( E# [' v5 h3 V- use MongoDB\Driver\Manager;
( I1 L) f0 M% O0 M- |0 P4 s/ P - use MongoDB\Driver\BulkWrite;* T" I; B0 ^( B5 E9 s
- use MongoDB\Driver\WriteConcern;$ s7 ], a$ P& }8 a, \* [
- use MongoDB\Driver\Query;( I4 e/ V, g' ], Z
- use MongoDB\Driver\Command;
& }7 l& {+ X( l' x' d
4 B. @# Y5 f" ?6 }) I) i* @- class MongoDb {
! e4 _2 P) s( M& V& U, b( H! F - : i R! G4 r) i+ N; ~3 q
- protected $mongodb;
& J: T' h6 `/ H$ a: E( ~ - protected $database;; R9 ~' h3 l4 A' m# y' W
- protected $collection;
7 |& P- S4 B9 u' c. Y - protected $bulk;
& K Y; X V# ^( x# [! V - protected $writeConcern;
- `% I2 g g1 |8 m/ i( X - protected $defaultConfig
$ K1 [/ V, x' H3 Y - = [+ G0 R9 G/ _9 H5 t/ V
- 'hostname' => 'localhost',
, @6 |4 o- |8 T4 l& J) j/ Q) X - 'port' => '27017',
2 X* {/ ?, n9 Y* X2 w+ N - 'username' => '',
! p8 \* y! F6 c0 m: g) ?. s! y - 'password' => '',4 |9 q4 k C2 {
- 'database' => 'test'
( P8 S, R+ A8 D - ];
9 U$ u* T6 L6 w; Z# Z7 }9 V - 0 A8 K3 ~& s* A! g
- public function __construct($config) {
: f) H: o1 t! l# P- k& v. W$ q; _ - $config = array_merge($this->defaultConfig, $config);
/ a4 w, V& Q. i/ Q2 J' H2 ^ - $mongoServer = "mongodb://";1 q% C/ _& D% K3 B( ~! L- `, A6 r
- if ($config['username']) {- U- a0 ~3 B- H$ q# A3 D
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';4 k. j$ X2 P0 [7 y, }
- }" R3 k9 j0 J* V, M. |0 T# e
- $mongoServer .= $config['hostname'];
+ e9 `0 K! p4 P- @* H0 R8 ?* z. { - if ($config['port']) {
( \8 h* x; m+ D# k6 t; ` - $mongoServer .= ':' . $config['port'];
( R. B! L% R d% S/ ?2 [ - }; M( U* g- V* M: ?8 x" K
- $mongoServer .= '/' . $config['database'];
1 F) a! H+ v* Y; f7 P1 B( Z - ! `: p: ?0 n. l( G( K
- $this->mongodb = new Manager($mongoServer);9 {; I {# i J+ Q7 `8 y
- $this->database = $config['database'];! Y* u! w- |- D; x- D I
- $this->collection = $config['collection'];2 l5 |4 S$ |. l) o- E. l* g% [2 E/ G; c
- $this->bulk = new BulkWrite();9 o" `. r9 j9 Q% F5 x! f' ]
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
0 \* x6 u S# A - }" a6 ~- \( O! i- M# c& ?
- ' Q- I( P8 n8 C) f$ O& a
- public function query($where = [], $option = []) {; a8 s' Q0 q9 y9 J0 k% g
- $query = new Query($where, $option);
' v, G; o& g% V4 F. L - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);8 v3 J I, A' N3 B9 @: }2 I) b
- " ]- f, ^9 b3 c- S
- return json_encode($result);. Y$ [3 d) l2 h( S/ F3 _9 n8 E" B
- }0 S5 C# a. }( B$ W! P. C
- 7 r# n* W1 }# D3 z
- public function count($where = []) {
3 j" K1 R6 ]" q) W P6 {4 b3 r - $command = new Command(['count' => $this->collection, 'query' => $where]);
/ Q; _# s# b+ p8 [ - $result = $this->mongodb->executeCommand($this->database, $command);% [& o) ~2 H- O, m
- $res = $result->toArray(); K& g" O. w" A c5 R; b& ]) k
- $count = 0;! O4 v& D/ | z/ p1 |
- if ($res) {
: G+ @' ^, @! d; y: A, v" ? - $count = $res[0]->n;7 m- b7 o& W, H+ E- x, u3 N6 ~. W
- } D0 `/ G+ I( a: P; t" ~7 J3 P$ {& s) s& m
- ! k! N* z, d( J9 n8 |# U
- return $count;
1 ~0 [6 w; G. q - }( D7 D u! a& M* J7 U s5 j ]
- 7 _+ U( {4 M) X: N( c
- public function update($where = [], $update = [], $upsert = false) {
- ~5 [. \. o$ f3 b5 | - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
+ S( S0 H5 o% M+ `; d( b - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);6 R4 I. T# _8 b. a; @
" V# ^7 f8 P/ y1 h& j& e- return $result->getModifiedCount();
5 j; C7 `- F0 O5 o% U9 U - }) g$ b3 a6 p0 A @
2 B* ?' K' h2 Y% R4 T- R- public function insert($data = []) {. i, Z: } ~0 J# a& O$ B" D& L
- $this->bulk->insert($data);, B0 h3 T: A9 `
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern); N* j) m" W' h* O$ C$ a) ]$ a
- $ w, v/ D$ R" j; {% i
- return $result->getInsertedCount();( @/ }6 d+ x4 a* e
- }1 P: m7 f9 c. ?6 O! [
# Z4 o5 t6 R' j" E- public function delete($where = [], $limit = 1) {! s4 b$ X& n7 o# z
- $this->bulk->delete($where, ['limit' => $limit]);
. B& w) \- ~% V, B% p/ m - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
8 j) M+ T6 }: l- p; P - 6 U: m1 Y6 i' [5 C0 L
- return $result->getDeletedCount();
. @0 V) N5 h! C; c% w2 e, | - }' {. n! V$ a j6 ~8 B
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
! c8 H+ Y7 W- c0 @% {; i 2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单. z* S% |6 }2 _; R `/ F6 x
- $lastId = $resultOne->getInsertedId();
( [$ N8 h" {, h* P - $resultMany = $collention->insertMany($array, $options);//多+ c9 z# |1 B; f2 t5 s" B. v6 Z' A
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
& T( y9 Y- V7 m! l- s; h( r
- $collention->update($condition, [
# P" p+ ]1 I2 C - '$set' => $values% K: [' v2 M- T2 R, o
- ,[$ E# Q" K, X! D7 l* F( S
- 'multiple' => true//多条,单条false! u1 q9 h# Y9 l
- ]);
复制代码- 新$ L6 p0 e* a5 B- a0 \! J
- $collection->updateOne(
- E" r' _5 Q7 y - ['state' => 'ny']," z+ _- Q) n v- x; B- p
- ['$set' => ['country' => 'us']]
% h) v. I% k: v3 W - );& y3 E6 g3 ]0 ?5 \8 Y5 `
- $updateResult = $collection->updateMany($ E; d2 g) @* M" q& E& W5 @: S
- ['state' => 'ny'],5 Q9 a9 Y4 X, s0 T' @* ^- ?/ [/ Y0 b
- ['$set' => ['country' => 'us']]
/ a8 w* A' `* Z% Q/ n - );
) G# Y- A8 r& d0 W% q. D T5 ^$ z - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
" Y5 r+ ~1 T! ~( W# N2 w
- $cursor = $collection->find($condition, [
" k4 y8 C9 ?' {5 ^8 @! {) a - 'name' => true//指定字段* Z" `5 R5 |. Y9 [1 _1 J
- ]);& ]4 Q/ p' x- s7 y% J' c* r
- $cursor->skip(5);) V- i9 q" l( E
- $cursor->limit(5);0 q+ e/ d) _* ?! [
- $cursor->sort([0 L+ w& j# b+ O: B# ?5 W& T
- 'time' => -13 L$ _: }2 J- [8 k* _
- ]);
复制代码- $cursor = $collection->find($condition, [
2 h; w, N. C0 O3 _4 D# e - 'skip' => 5,3 m B C2 H% A2 L
- 'limit' => 5,
6 @+ H( k4 h0 ]$ m0 j* \4 w. M# ? - 'sort' => [
1 w9 ^8 a5 q, S. i - 'time' => -17 r6 \$ D9 i( |% Z. i
- ],//排序. E3 @$ J% M; w/ z$ W* w6 D
- 'projection' => [
9 \2 d$ q$ `/ j7 _; C - 'name' => 1//指定字段
* W2 Z! e/ N( [0 | Q i) i2 f - ]' m; s# W$ U: a9 ^ I3 L9 V
- ]);
复制代码 5.删除- 原+ ~' t* j$ O) ~# e4 A1 C
- $collention->remove($condition, [# F7 g5 c: _0 R) a# A3 Z- g/ H
- 'justOne' => false//删单条
# |/ `( u1 Q, c8 ]& ~3 _ - ]);
q7 c$ u+ }! ? t- u! M. ~1 o - $collention->remove([]);//删所有
复制代码- 新6 q, K8 y* t) {) Y3 J& }
- $result = $collention->deleteOne($condition, $options);
: ] n% h9 {6 H' p - $collention->deleteMany($condition, $options);$ j' y) d# n, Q, s+ y7 H5 q2 P$ r. T
- 4 }, G( G! [4 U& c4 \) p; R- W
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([+ `! I2 r: q( K% h* y! g8 n
- '_id' => $tableName//我在自增表中用其它的表名作主键
, X) c# M. w, T9 r: U1 L7 M - ], [4 e- C& l1 d$ z1 O4 d* ?
- '$inc' => ['id' => 1]//自增4 m4 K$ G2 }5 r0 N4 O
- ], [
9 d I# V8 C) H, Y; M - '_id' => 0
$ u% A- y. N0 P8 G% @5 v; Y - ], [$ K. m' D# q9 e* }6 v- N
- 'new' => 1//返回修改后的结果,默认是修改前的
$ O, {: f' M, k, P$ W' B: g7 \ - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
2 }( b [4 b, q; s' |2 _( H - '_id' => $tableName
: H9 c# n0 m5 h - ], [
# u! j* [/ }) C5 [$ p# A - '$inc' => ['id' => 1]
$ \5 K& Q8 s1 y - ], [3 v7 J0 s/ u0 u R
- 'projection' => ['id' => 1],, l! t: n j z& g `5 ]
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER6 F& i, {. v* ]$ T
- ]);
复制代码 0 u( N: Z5 S- L$ N; m8 d( |
. D0 ? n6 s5 R* J' [' [3 ` |