使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php; I3 E8 I, E# m; n: _! A, ~
' M/ P( X" p' `- r- R2 t- use MongoDB\Driver\Manager;
, [. C/ @# C" F4 i- N0 j/ \7 Z% _ - use MongoDB\Driver\BulkWrite;2 J7 Q* O4 r$ x. Z) n$ ]5 M
- use MongoDB\Driver\WriteConcern;' W) i: g/ i( X/ ]5 o0 i( ^
- use MongoDB\Driver\Query;' X+ P% ^" {) K/ x
- use MongoDB\Driver\Command;
; [8 c9 z. K# e H' d) m0 t - % }% q! l! H( R
- class MongoDb {8 R2 a/ {( l7 b3 t! K, K' R$ z+ i, y
- 9 y# I7 H# J& `. M, Q6 Z- M
- protected $mongodb;/ D/ s: e( |( ^6 p; u( a. L0 d* A
- protected $database;
0 s" E: X; P2 x0 \2 m. M, d" O - protected $collection;3 q) S1 T! v5 v
- protected $bulk;" y% k4 P) G% h( @
- protected $writeConcern;
# t1 f t5 J1 V - protected $defaultConfig, c0 W4 O- p# R2 |0 e/ i
- = [! B* A6 e- w1 v+ D" _
- 'hostname' => 'localhost',
; q+ h, R. d/ n1 w$ ]0 [8 w - 'port' => '27017',5 v4 c2 x$ E3 o/ \
- 'username' => ''," s8 ~# A# @4 Y; \& \( s; ^/ p
- 'password' => '',
" V) r) @: I+ a5 A. ? - 'database' => 'test'* G( R5 Y8 ]. M1 U
- ];7 F% a$ T; L8 F- u
- 7 c3 l' g' d- J2 _9 h
- public function __construct($config) {
8 @; @4 _6 n9 g3 N V# h9 g - $config = array_merge($this->defaultConfig, $config);. x0 z( R' N8 D6 K; a/ A j
- $mongoServer = "mongodb://";' P2 c" d* J$ M x4 s
- if ($config['username']) {
/ X& t2 x9 w8 B3 P8 X - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';; Q! W8 z5 p0 w, |0 p7 e
- }
% u6 R) w5 Q: G' o7 B4 @ - $mongoServer .= $config['hostname'];
- U w0 P* D# G& g( T - if ($config['port']) {7 ~& N3 _5 T9 V$ X; c5 ?) N1 c
- $mongoServer .= ':' . $config['port'];, _- G% H7 Y( d+ M. N& T, |
- }& V: v* F$ ?0 f' i7 ~
- $mongoServer .= '/' . $config['database'];8 p2 Z4 Z0 K. g4 `2 y3 ?' o
- 7 W' n' r8 }8 ~ G. ^
- $this->mongodb = new Manager($mongoServer);
; {0 z6 Z/ p: p& w - $this->database = $config['database'];/ H2 L8 n. r# v. R( I8 Z6 E
- $this->collection = $config['collection'];
) t8 ?4 ~8 N: k# W" U& z* P. [ - $this->bulk = new BulkWrite();
/ _9 U0 Y- i* d" T - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
: B- p- Z) I$ ]( t- L [) s: a0 }- a - }
% _$ u3 ]' |0 U7 A2 Z1 T% i - # i6 f7 \9 ?4 n4 d$ \ \
- public function query($where = [], $option = []) {8 A- g, ?, p4 `+ S
- $query = new Query($where, $option);
1 Q& T+ K2 a0 w% Z - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);# w, B4 @9 Q& U/ g0 D) W
- & r9 X3 [6 b2 b* }
- return json_encode($result);" G, L, M" R& f0 t f9 J5 l- J$ [
- }: t: @) _: L) r1 X1 \% o4 J
! |4 ~# o/ w$ [& w: f/ o4 i8 B- public function count($where = []) {% l3 R- I/ U/ E6 c4 I
- $command = new Command(['count' => $this->collection, 'query' => $where]);
4 ]) }( M" z+ X9 y& p - $result = $this->mongodb->executeCommand($this->database, $command);
9 u- P! d5 l$ j- K8 G( Z3 Q - $res = $result->toArray();
- f' w! X: O, u5 z' B - $count = 0;) Q- v- Y# U+ s
- if ($res) {& C8 m8 J0 E% c# J# ]
- $count = $res[0]->n;
( t5 A4 [) n+ }/ A: y" V) z - }5 d6 R$ Z& Q4 M( ]' h' x
: c9 y6 r7 G- E5 Q9 V0 L) u- return $count;
" P9 o" m0 d# ` - }
1 j) W$ f5 v# j# m - $ L. G+ V# s( G! T6 m
- public function update($where = [], $update = [], $upsert = false) {0 E6 n$ P" ~4 ~# o' G2 Q e
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);+ F+ m z3 ^! ?; O, s
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);& ^" [1 a: s) y" A2 \& y
- * P& r i0 ^; {) b% o& C" g1 a
- return $result->getModifiedCount();
1 C- [! R8 U& q& U - }
I4 U9 |) r& c. {, J9 p' D Z
. a' ?1 L9 _5 f: K, h- U- W- public function insert($data = []) {
8 e2 G1 u& k* j0 G3 _ - $this->bulk->insert($data);! s5 {. o6 s0 n" J" w+ X6 ^) M
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
7 ?, m! _) O0 c- |) j9 i% |0 g
6 G1 J4 @) S/ f, v/ J; h7 s* ]9 w) Z- return $result->getInsertedCount();
8 e& ]; A. M5 [" ~5 V2 O - }
b7 p# g8 H8 x. V - * i( p) b# \" ^; T6 ~* h6 c5 G
- public function delete($where = [], $limit = 1) {
/ A7 B# i! t4 | - $this->bulk->delete($where, ['limit' => $limit]);. a- M) A# S5 }1 l: L+ v( O
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
, `; c: T- h5 K* F+ `. {8 C) Y
2 B* g4 E. U4 Z' O6 l* j& U" b- return $result->getDeletedCount();
- W' d5 C. \8 r; X2 S% D. O* ]& r - }) a B/ H; A3 Y
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原1 n9 C2 {% @% e: E! z% x
- $collention->insert($array, $options);
复制代码- 新8 Y$ k) ?8 a( m8 }% v6 ~
- $resultOne = $collention->insertOne($array, $options);//单
* k: q" h" R' ^8 K; _! D - $lastId = $resultOne->getInsertedId();8 L9 c6 }9 H2 W/ D
- $resultMany = $collention->insertMany($array, $options);//多
1 p/ z6 |4 W. f' K - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原4 @) i/ T: y3 L0 R# J/ l# t
- $collention->update($condition, [: F: \7 Y3 \+ I$ H1 T
- '$set' => $values
. a. Z8 T! R. @ - ,[
& x) B r% v# j9 n - 'multiple' => true//多条,单条false5 R, O+ s: q f1 Q$ b% f5 A7 L% V
- ]);
复制代码- $collection->updateOne(. X& ^- z4 F" y& T) a, u. X$ q
- ['state' => 'ny'],! i: `( n4 H8 i8 J
- ['$set' => ['country' => 'us']]
, f6 R9 t# e) C - );
' _0 p9 M+ C, l) t; o4 z) V: i - $updateResult = $collection->updateMany(
: U8 j# `) j; g - ['state' => 'ny'],
8 b, X9 F6 j2 I- ~5 n z - ['$set' => ['country' => 'us']] J$ j w$ J2 Z* }; V
- );
* o# h1 n- _! x1 j A - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
' Y: k, ?: Y% Y7 U6 G$ p: v1 i
- $cursor = $collection->find($condition, [% t* f1 T. T( u+ e7 X* N" {
- 'name' => true//指定字段
/ s' q7 w1 G7 A - ]);: X' z/ Y H( V4 t
- $cursor->skip(5);9 x# u7 k6 M) G* y2 ?( b
- $cursor->limit(5);
) G' g* M6 J$ C9 z; {* O$ g8 I# l - $cursor->sort([
' u7 H% j0 {1 B7 c; p/ e% d - 'time' => -1
+ j f. X# E/ I" n0 x" ^# V; v - ]);
复制代码- 新
5 F. S5 t- L2 n, J& f# Q8 ^
- $cursor = $collection->find($condition, [7 k& _8 B8 }2 s1 Y; k
- 'skip' => 5,
" x& O; g( |; {7 `/ B9 l7 T8 R - 'limit' => 5,. y0 M6 G( h! a9 t) q: q
- 'sort' => [
+ |. C* a3 h8 |1 Z: y - 'time' => -1
6 r1 c$ I) e% z$ s - ],//排序, X x7 z3 h/ p0 N1 } t+ t7 W
- 'projection' => [
i) G9 ]$ O+ `% H! i" [- C - 'name' => 1//指定字段2 k, y. |! {/ K' z
- ]
( x g' W( o; ]5 _7 P6 U' ^' F5 P - ]);
复制代码 5.删除- $collention->remove($condition, [
- W% \* S5 H2 o2 K3 y4 ] - 'justOne' => false//删单条
& C& N( E' R) B9 A; s g - ]);
5 f! w2 R' m) v) m - $collention->remove([]);//删所有
复制代码- 新 J5 B; O) W9 P4 `8 y9 r: b a
- $result = $collention->deleteOne($condition, $options);0 q; @4 W# a# Z5 _, N1 }& |8 q
- $collention->deleteMany($condition, $options);
5 `/ T0 ~4 V1 G) ?6 u6 X - 6 D# L# A" i' p: Y/ w/ S' ^( A5 ~' \
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
1 m' d$ l( H, T, l H - '_id' => $tableName//我在自增表中用其它的表名作主键* r$ l# W8 ~2 W4 E$ E& `: n
- ], [
! Y( N5 `( T' v$ i; H+ x8 r - '$inc' => ['id' => 1]//自增3 I1 u& A0 o3 r' ~+ f2 P
- ], [0 K/ G) F% X! Y! ?7 g$ F
- '_id' => 0
8 r/ t$ A3 G6 A! D - ], [
& R2 \% x& u7 m2 Y, N - 'new' => 1//返回修改后的结果,默认是修改前的
& e$ T& x0 ]2 z) ^6 e& w - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([4 L5 |8 E/ _! j# \2 s0 j5 a6 Z/ y
- '_id' => $tableName7 m+ s0 H) \; S' D, y/ A
- ], [0 H- r' U! ]4 x' r) |
- '$inc' => ['id' => 1]
! x! q Y0 L0 J1 x# G X: L - ], [; Z" n; ^; {: j# |5 {9 ?8 C
- 'projection' => ['id' => 1],
U8 `8 W/ Y! A& @. z" m - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER, c; p4 C# D* D5 l$ l
- ]);
复制代码
* b v- u1 E* x- V6 r- d
/ r1 D% h$ A: V6 i5 o8 S |