使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
. _! z y! V' |, q( S& Z
4 C' `/ {$ \- ]( ~: D- use MongoDB\Driver\Manager;5 W4 A0 N# C# [* D l$ {# T( ?
- use MongoDB\Driver\BulkWrite;
& ]% |6 t8 p4 J; e - use MongoDB\Driver\WriteConcern;
0 M g( B' j8 d6 X. A - use MongoDB\Driver\Query;
/ U1 }5 H3 V& [% P1 I2 F4 K& N - use MongoDB\Driver\Command;
( ~7 p/ ~( c9 j/ ^/ |, N: S2 G
* q0 O: ]$ M k' W- class MongoDb {) ~, q& i( A: g/ V* t3 Y+ x, _3 f+ F2 e
- g2 J7 g- f3 M$ d) l7 W* i- protected $mongodb;
3 ^& s9 g+ T) S3 {% D - protected $database;
% m! q& Y1 C- ?& ^* n" @) _6 V - protected $collection;
+ v4 ^; ~+ r% U5 w& \ - protected $bulk;
& d% J* ?! I0 E; Y1 _' ?& Y3 X; ?3 I - protected $writeConcern;0 v v& b; V% s# S( {4 }
- protected $defaultConfig
$ w( A, Q+ F0 G0 g! p/ O" u - = [
' Q' }* M9 F/ y, c( V) d/ M1 c - 'hostname' => 'localhost',7 n C, H% r( a5 |
- 'port' => '27017',4 b+ w9 v& y5 O- l6 o
- 'username' => '',3 a1 c% E# x' g& {! L
- 'password' => '',: `, C# n, \2 W8 S1 s
- 'database' => 'test'
' L D& U3 I8 G9 z: b: } - ];
/ [" s2 A' F+ T) h2 q0 L
! m8 V9 K% T1 L/ @4 {/ }: D9 ~- public function __construct($config) {
4 X$ a6 b0 P+ m; h; A2 T. j - $config = array_merge($this->defaultConfig, $config);
# P6 P* l1 N! m7 M1 Q: q& l - $mongoServer = "mongodb://";
, S( Q' y6 K4 \. s0 j" _; y. R" }9 P - if ($config['username']) {) t, d4 M. Z) z
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
, @$ f- x) S5 R1 r* H6 u8 G - }1 L9 g5 Y: p: Q7 X' Z
- $mongoServer .= $config['hostname'];, |* I. x" P* _: H @: T' M9 P
- if ($config['port']) {
2 i6 B% g+ H7 A0 F$ q - $mongoServer .= ':' . $config['port'];4 \2 p+ R2 | T5 d
- }
$ s' \( ^6 W# U' u6 p; c, z - $mongoServer .= '/' . $config['database'];% _) \1 r z) b
- $ X# E3 n; Q/ ]6 n0 J, K$ D) F0 |& m
- $this->mongodb = new Manager($mongoServer);- F9 C! e, {+ V" c& f1 O3 l* Q! b
- $this->database = $config['database'];
* h/ @; z" K. Q1 {. c& {& p - $this->collection = $config['collection'];: [: u3 Y9 Y& u% U: c
- $this->bulk = new BulkWrite();, h% I( D. D, {5 j
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
- @& w/ I( g+ g( y4 d - }
+ ?3 \6 m" P) H- e - 5 w3 ]) ^+ m3 i- @. t9 r
- public function query($where = [], $option = []) {
, S" Z, @% E+ t5 j1 ` - $query = new Query($where, $option);: W: H; o+ q6 B7 Z4 a1 Q5 {
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);% h$ f0 r! ]0 N
- ) u% y) F0 a5 V9 A. u
- return json_encode($result);% Z( I* H: q- F( ~+ s8 n, i
- }, U$ C8 ^: D/ ^1 W
- $ W& I! m+ j4 N
- public function count($where = []) {7 S1 K ]- N- d$ } Z
- $command = new Command(['count' => $this->collection, 'query' => $where]);
1 m1 C+ m, P, ^& X0 h z- j - $result = $this->mongodb->executeCommand($this->database, $command); e; R7 s$ w. A" R0 d
- $res = $result->toArray();8 N' m3 J; R8 n" I
- $count = 0;
+ G1 P q% a, o4 S* d3 l - if ($res) {
$ ?0 C+ k: k5 G1 V& [1 K - $count = $res[0]->n;
2 A3 A! X7 n( e) q5 C - }+ ^) D, u4 J8 t) j5 }& r
0 q; {. G7 }5 W- return $count;5 J( o& }5 w. L
- }
) W0 [% s5 J( C4 e; {3 `. I - ! t7 n# u3 D/ H- D
- public function update($where = [], $update = [], $upsert = false) {
7 [ o9 F6 G F( z/ P1 R - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
7 s. Y0 o! k% C. W: Z# i - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! R Y1 f3 i, E$ A8 O
- ( j6 h4 }) o& c2 R/ ~/ ~1 C
- return $result->getModifiedCount();$ t0 U9 U" ^- `/ c0 J/ T) w$ w, o
- }
( r+ c! I0 E# p. N6 l2 g7 N
5 q/ a! v i. q1 g3 m- public function insert($data = []) {
8 ~& Z( a9 R' i. ` - $this->bulk->insert($data);6 k: Q* @. ~2 P
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
9 Q# P+ L/ K* C
2 w( L0 y ?9 l% ~7 B5 Z! R- return $result->getInsertedCount();
* R6 q/ n0 W+ l+ o - }1 `) C$ \& c# A* y4 \! W1 F
$ q5 N9 t" j8 j9 C- public function delete($where = [], $limit = 1) {
$ ]! ]% b l" J O9 Z9 b - $this->bulk->delete($where, ['limit' => $limit]);# N: I" k# ^+ ?/ q4 S9 ?# f
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
! P2 c; q2 B' _9 z% J - & v1 w( W$ Q, b5 E
- return $result->getDeletedCount();; N5 M, h {- ]( A# r. U
- }% ^6 g3 |8 I$ F A2 q3 S: R
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
. w8 l3 ?) @. q) O$ V* H
- 新5 m# C4 Z9 M/ m$ D$ [, ~& ^- @
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单$ g; I' O1 G3 I# z" G" b7 s* G# a
- $lastId = $resultOne->getInsertedId();* Y+ o0 h \6 [" H6 \7 m& o
- $resultMany = $collention->insertMany($array, $options);//多
" f$ ?; K( q5 f3 r - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
0 u1 }2 s. l0 Z, {( G; Z4 v
- $collention->update($condition, [9 w! I: e: s! j1 Q& r3 t* U, o! s
- '$set' => $values
, e5 V! n- ~8 U8 r, C1 d; R - ,[
* r7 J( a4 _4 {+ O x) X - 'multiple' => true//多条,单条false
* x9 M$ {3 ]$ Y# g* N2 \ - ]);
复制代码- $collection->updateOne(
! V0 q$ V0 B) n" Q1 }0 Z - ['state' => 'ny'],- X! h) @; V+ Y
- ['$set' => ['country' => 'us']]
! l; A* |2 z% m8 _ - );
% P# t) u/ G% w0 R: M6 S - $updateResult = $collection->updateMany(
4 `: y# s% n: ~# ]+ k - ['state' => 'ny'],
8 l4 o% @2 m b$ r c8 j - ['$set' => ['country' => 'us']]
d9 U, o; `6 P - ); @) C+ Q2 Q. }+ A
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
4 G* _3 @! X1 }. }. S( Z* Z - 'name' => true//指定字段9 u* p# h2 n7 ]: D4 B7 M" r
- ]);2 w6 B; z1 @, U! I$ `
- $cursor->skip(5);
- w0 |- [! y: \8 j9 P - $cursor->limit(5);# t# J" l4 _% y/ `1 h" w- c
- $cursor->sort([5 c3 I' M6 G9 x3 n! J. ]
- 'time' => -1
! u0 H5 b$ h3 s' l* p; l - ]);
复制代码- 新, S# C# N: X9 u; S q$ c" I! q( m
- $cursor = $collection->find($condition, [
+ q( d3 F" v1 @7 W0 D - 'skip' => 5,
' d) E) T7 W' O' K& j3 I e( i4 D8 E' @ - 'limit' => 5,
) W9 ^2 y% @ O( } - 'sort' => [( _+ M* N: l0 s9 }
- 'time' => -1
6 s6 [. b8 J0 D6 q) R; m - ],//排序
/ a' u/ i. I1 e1 V$ Q" O - 'projection' => [ ?% C! @* K# G5 s& A
- 'name' => 1//指定字段5 D+ d x: Z- @, V# `+ I
- ]5 x7 C( O5 o# K# _
- ]);
复制代码 5.删除- 原8 A m/ ^' u7 t! n3 G: b2 J' P% q6 `
- $collention->remove($condition, [
' V9 W6 U. g9 z; R - 'justOne' => false//删单条* ]# d2 _; D4 t9 ?& I% b1 ?
- ]);8 R- D5 g3 q% n! O1 u# q
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
" n7 o7 |3 E$ _' G! G4 D - $collention->deleteMany($condition, $options);/ F: m, @9 C0 x) C% r7 q) h
- , g% z% ]9 |& w" ]$ f
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([4 D: g, L/ O; B c+ A( j
- '_id' => $tableName//我在自增表中用其它的表名作主键
5 ], P$ a. C7 v/ Q - ], [
) [) _' \9 ? i4 N2 i: p6 F - '$inc' => ['id' => 1]//自增9 N9 S) S2 u9 B; l0 P$ X
- ], [. I8 h9 ^ B9 V- k
- '_id' => 0$ J1 F% I/ [" n
- ], [
% P6 V3 t/ s. A2 B4 N - 'new' => 1//返回修改后的结果,默认是修改前的4 F T w( f _+ I2 Z0 w
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
( } w" s$ G. _ V" K& [ - '_id' => $tableName# H2 s" g2 f% ?" z/ D- ]7 m
- ], [
2 I9 A+ {7 n% f: t% C1 T - '$inc' => ['id' => 1]) G0 Q! r0 a6 f$ Z5 K
- ], [
/ I1 e( H' q1 W+ N - 'projection' => ['id' => 1],
! S: V0 d- j) L- g7 v - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
4 {' D& ]% i% }, v. J- E5 M& A - ]);
复制代码
1 C' J, _% Y- G7 v2 }* i, `7 K, R
# n6 O# D* X, z# z" s |