|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
2 u, I' Y+ l8 b" B [9 I' m
, r! y5 `" m j u9 f+ [- use MongoDB\Driver\Manager;
, u: {5 J3 }: ^ - use MongoDB\Driver\BulkWrite;
! W( q+ H; z4 C. A: D# c - use MongoDB\Driver\WriteConcern;1 g6 d+ p3 g; X3 X1 K
- use MongoDB\Driver\Query;
' B. j x7 W- P' @7 t% b O; ] - use MongoDB\Driver\Command;
5 ~5 M7 l% Q5 I; F. n2 Z2 t! ~ - 9 c+ x5 f$ m9 l: L& X1 @* C
- class MongoDb {
k2 v* t3 {* ]/ P% p' d9 ^' |/ U6 z
$ [ I. r8 L# J( V! B3 E- protected $mongodb;
7 U$ ]4 x8 z; E1 ~: x2 z) w - protected $database;- ]3 o* C& N& T" W4 I2 D4 p1 e7 Q- s9 J
- protected $collection;
! P/ {( D, @" o7 { - protected $bulk; B# B3 a3 U. p7 [! Q, I, N
- protected $writeConcern;
0 M+ i& Z$ ]/ {+ _7 p# k - protected $defaultConfig
B4 G5 g* W3 n8 T - = [. `5 B g+ p1 w9 w" h% [6 m
- 'hostname' => 'localhost',
0 B) }+ P& c1 B: G3 [7 A9 J - 'port' => '27017',
2 I% N- T: K, D* {" [9 [: W8 \ - 'username' => '',8 v" w& h' ]6 x% C
- 'password' => ''," J8 i0 G7 I ~, ^+ l3 {
- 'database' => 'test'2 h) R% X: G0 ]: K- F: `2 T% W& ~
- ];& r( o+ N# V( ?
. N9 o t, z* Q1 s$ c- public function __construct($config) {6 O( s3 D! T8 O1 e8 h$ }
- $config = array_merge($this->defaultConfig, $config);% X' i8 d$ z5 L0 l \1 W
- $mongoServer = "mongodb://";
$ D2 z# y3 h) H, J - if ($config['username']) {5 b! a. b& d3 Q* i# C& w- R
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
, A) C$ u7 d! H - } L2 ]' f. w; M8 W
- $mongoServer .= $config['hostname'];
5 F( K, `! V+ z( k1 U - if ($config['port']) {
/ @! }; o! R, ?4 r G( P - $mongoServer .= ':' . $config['port'];5 o# I4 ]8 K8 {( N& |& b
- }$ n% L8 L2 d: B+ I! l
- $mongoServer .= '/' . $config['database'];; K2 D) d+ p4 q3 L' P& w4 ~
- # m8 i# o" W- ], b$ _5 I
- $this->mongodb = new Manager($mongoServer);
, w$ |0 O( }6 `% y% l - $this->database = $config['database'];
0 b! @. D( z R2 t# w' ? - $this->collection = $config['collection'];% C b$ c# J, g' R, l( g/ {& L/ B
- $this->bulk = new BulkWrite();; B6 `) L2 f6 D+ u0 E
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100); W' O V/ V* u+ S% L2 K
- }- H; O! _ t' g0 F" p" B" B# q L& t' y
- # P9 F3 q0 K% A; r6 w& V: x
- public function query($where = [], $option = []) {
2 y8 C/ e4 O2 {0 g, C - $query = new Query($where, $option);
5 m% o7 w( o$ a1 P) b1 {8 C! _ - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);3 ]. r' O' b6 O
Y" N: e I+ |# k9 ]- return json_encode($result);* O/ ]5 e7 B6 R. j% w
- }% @4 e3 z- {2 f( J# E
+ A& w# _+ G- ~) J- D- public function count($where = []) {/ U! o0 t! n0 |) C
- $command = new Command(['count' => $this->collection, 'query' => $where]);0 q! C' M4 X% z7 K h- m( ?
- $result = $this->mongodb->executeCommand($this->database, $command);
9 s2 v" _2 _* @0 F - $res = $result->toArray();
1 H0 f/ x5 m; E, u - $count = 0;5 Y* W! P; n4 r4 F
- if ($res) {
2 S' U( R a8 l- Y/ z, Q- z - $count = $res[0]->n;& h& M3 P7 b! P( p7 h$ N* n
- }6 S' f, Y2 G) R% G% t
9 B& X8 Y7 H& S% Z/ e7 ]' o4 @& b- return $count;& X3 Q3 F* \- f
- }
" B7 B2 S1 R0 _" W4 V. C' Q
! i: Y: |, q! S( s- public function update($where = [], $update = [], $upsert = false) {
* q" H. W, s' F. i - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);( \' w1 r; ?0 o) \
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
! u0 O; r5 p$ V9 Q+ g6 H - 9 o# c& F$ B& X) O% Y( e( g
- return $result->getModifiedCount();" k. d0 l* o% @* B% d
- }
* N+ [ a( S6 V4 l: Y9 L$ x - # v# O! b# ], W5 R8 R
- public function insert($data = []) {
3 p4 q4 S I5 I9 Q+ w& ` - $this->bulk->insert($data);1 H0 x* _ v- _2 i
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' L) v/ X U+ J. D
( {* o7 B4 F$ S- return $result->getInsertedCount();
4 I! Q# h. T5 V/ R; t - }. v. d5 A3 F3 v- ?) P
- - C& H5 R& O* b# U- r6 c$ }
- public function delete($where = [], $limit = 1) {
1 r/ K+ i, v; R4 A, B, n6 ] - $this->bulk->delete($where, ['limit' => $limit]);. A# O" T9 v& y- {" Y
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 u5 ?; h, `" R; J# }: Q* s6 b
/ j) {0 I$ k: {0 x1 a' e- return $result->getDeletedCount();
$ |5 E5 c. Z$ z; H# C7 P7 ? - }
x9 H" C! K5 G# x - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
' s' O9 C ~+ q# {3 [: C 2.新增- $collention->insert($array, $options);
复制代码- 新7 V: y! p7 z/ c/ u% t% F% D
- $resultOne = $collention->insertOne($array, $options);//单
) X2 d) H* E8 Z/ w - $lastId = $resultOne->getInsertedId();
4 [$ Q$ |( ^ \4 Y - $resultMany = $collention->insertMany($array, $options);//多$ l+ l+ [& m% ?& h9 F9 D
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
$ P) t! F# U& C" Q4 `/ j/ C7 C
- $collention->update($condition, [
1 k4 L7 O, o6 x8 {$ s - '$set' => $values6 X1 x2 A* e0 @$ l
- ,[
4 D7 n! T7 C4 z# L9 Y, V9 y - 'multiple' => true//多条,单条false
* a# P% |) m) n t, W: G - ]);
复制代码- 新
. b; I7 Z$ Z5 L' s/ d6 Z6 }' H
- $collection->updateOne(
6 Y; J9 P, ^2 { - ['state' => 'ny'],4 U( Z3 G2 r! ^3 K' V! J" G
- ['$set' => ['country' => 'us']]9 @8 @. |* M+ ]1 D; _6 }9 @
- );2 K' @6 I/ I- ?; Z# j
- $updateResult = $collection->updateMany(
6 u9 {7 D0 B: i. Q4 I1 g, j - ['state' => 'ny'],
0 S" Y2 H/ r0 K6 O+ S; i - ['$set' => ['country' => 'us']], n* }- d, u- {. v# M. h+ G
- );
4 ?# h3 A* U7 o. }8 A" i8 ^3 ~ - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
9 R# @2 V" I% X0 ]2 E% u' }
- $cursor = $collection->find($condition, [; l) {+ u# Q8 g8 S+ h
- 'name' => true//指定字段
( Z. h3 }+ J. X. E8 W& {2 @# j - ]);
( J y; t0 ]( r( h* _ - $cursor->skip(5);
5 M0 L {5 x( n2 b7 ~5 Q3 v - $cursor->limit(5);) q, S" _) s+ w1 s9 e
- $cursor->sort([
( V1 f7 O* v( ~$ o2 O! c - 'time' => -1
: _+ ]( c- M4 e2 |5 `' m5 V3 | - ]);
复制代码- $cursor = $collection->find($condition, [
" a5 o# m) o# b! V; m# q. B! D - 'skip' => 5,1 T$ o" d+ L, W- a3 e! r& r1 D
- 'limit' => 5,2 j$ F" N% j8 t' T* J" C A1 J
- 'sort' => [# @& v0 n8 D/ w; R% Z
- 'time' => -1
: ?' w/ @, |% L- n. k) b( H - ],//排序5 b. V: ]1 a- _
- 'projection' => [) G: A; }5 y L+ X$ z6 K
- 'name' => 1//指定字段
, `% y! ]- _2 j' a - ]
7 n2 m1 |5 g7 Z2 ?* S - ]);
复制代码 5.删除- 原
! ~' O3 J- C& v- P& p2 q( {' r7 L& @
- $collention->remove($condition, [
) s- E+ I, y8 p1 E6 m+ s - 'justOne' => false//删单条& z6 X2 v( ?& ^4 Q/ c( x! H
- ]);
) s+ e7 H& o# J - $collention->remove([]);//删所有
复制代码- 新
0 c x0 k' v9 n; i1 D9 ~
- $result = $collention->deleteOne($condition, $options);
- B! L+ {: |" C. Y3 q+ {# } - $collention->deleteMany($condition, $options);# d7 ?. b+ I8 t8 `9 X+ R/ ]1 U
- # v, n5 B1 Q, {& P# ?+ w& p
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
% ?0 g5 p) z _" L9 v9 e/ s - '_id' => $tableName//我在自增表中用其它的表名作主键
8 B0 l+ |( Y/ i2 {& r. X& o! _ - ], [
: ]5 A |# ~3 q3 E - '$inc' => ['id' => 1]//自增
' v$ h u$ M! g `" b* n( s - ], [( U6 K6 p5 w) W/ j( s' s
- '_id' => 0% Y4 Q5 g) r4 y. q
- ], [
& B( f# n3 J1 R- S; [% t- }' {- n! E - 'new' => 1//返回修改后的结果,默认是修改前的
. M5 u5 t5 P( X - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
8 ]/ }0 O% I2 J2 U7 \ q$ H - '_id' => $tableName: b" @% k, I: P4 x: L( B) r9 y
- ], [% U% d9 f+ \: n1 {/ j# Z y( n
- '$inc' => ['id' => 1]0 _0 E& |) p& h
- ], [. Z/ i( i! K5 _
- 'projection' => ['id' => 1],
+ x2 [. i1 z! e" k8 ] - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER& s2 k1 f$ a0 J
- ]);
复制代码 5 }1 B# ^: C6 J) J
) X& a8 ]/ _; D% l' d* _6 ` |