使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
: U+ r+ B7 G3 F! ?& k$ }# ?. M) f
/ u& P& W' ~7 _4 q+ B. x0 x; D- use MongoDB\Driver\Manager;# J: p4 k5 p9 |, Z
- use MongoDB\Driver\BulkWrite;
1 H* A5 Z5 i5 [; U9 S- u5 o - use MongoDB\Driver\WriteConcern;
/ K/ J) b" _1 {1 |6 f9 e - use MongoDB\Driver\Query;
! {; p3 p* e" \8 s/ X - use MongoDB\Driver\Command; W2 ?, x7 T- E3 n4 I1 a# i4 ^* {) _
- : h5 Y* I) U- E& @6 C
- class MongoDb {
- }! o0 n" p d% ?; X7 ~
# e$ H d$ k/ E1 v' l- protected $mongodb;
, U# e$ S3 @- K( f - protected $database;
* b8 {+ @7 N) F" M! ^ - protected $collection;! u0 s' h8 B; o
- protected $bulk;! |2 t( L9 _; n2 U# U1 H! c1 h
- protected $writeConcern;% }" I' C% m% }9 b; X" U
- protected $defaultConfig
; x4 B+ L" r9 G) z) @; s - = [( N$ Q7 T( c* V8 M
- 'hostname' => 'localhost',
) T. d6 } P! c7 v - 'port' => '27017',
( G8 W# G( x* ]/ C - 'username' => '',
6 D/ J, o! {; q. Q+ z - 'password' => '',
: u- q9 o( s4 _* g - 'database' => 'test'9 _, S0 I& c2 H# s! P( j% Y, U" b
- ];
z/ }: Y% `0 J' D( o4 x - ) _4 p- x% j8 D0 h
- public function __construct($config) {
! T2 e; g" R! n2 p4 @% _# ] - $config = array_merge($this->defaultConfig, $config);2 s% h/ H$ j( I# m
- $mongoServer = "mongodb://";
6 e0 o0 E% c; ?' x& K7 C F/ _ - if ($config['username']) {
5 d* C: z# m6 \+ ]7 t, i M - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';& E5 ]! G) W, @) S5 V5 s
- }2 D# c1 M$ y, g+ t/ ^5 B
- $mongoServer .= $config['hostname']; H2 F- ^5 k' E0 u3 E4 ]
- if ($config['port']) {( d* X+ I2 o( w8 k
- $mongoServer .= ':' . $config['port'];5 b# u! E* t' c& ]) W+ S6 W
- }
3 y: ~! [- d0 U, |# H - $mongoServer .= '/' . $config['database'];
! |; N" O8 z% X4 {1 C/ h - 7 D) @& B( `' ?+ }8 B+ o5 }
- $this->mongodb = new Manager($mongoServer);
+ U) K2 ^" V3 M: s3 h7 n) Y - $this->database = $config['database'];/ j! ^5 V" g2 U7 E
- $this->collection = $config['collection'];
2 v% C3 s3 z8 M/ p; V - $this->bulk = new BulkWrite();3 ^8 h3 J+ b; ^* d
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);+ J# F& ~, z4 }- X5 ~$ S! L
- }0 D% x# Q) ?- |7 t* k9 j4 ~
- : f& z& U1 n1 C$ d7 ]" M
- public function query($where = [], $option = []) {
. l( N, J( J4 r; x$ s+ g - $query = new Query($where, $option);! ]: ]5 P6 r" B# f$ I
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);/ f- n: r& z* L U- K. Y/ P
- 8 g( G' |& T; Y$ Y% D
- return json_encode($result);) L! n' P6 t6 E' a
- }7 b% d8 E. x% F
- 2 r$ G/ }4 d M1 C' h4 I" l7 W/ u
- public function count($where = []) {; \: G2 d" l: q) J
- $command = new Command(['count' => $this->collection, 'query' => $where]);
7 w9 ?/ K. H N - $result = $this->mongodb->executeCommand($this->database, $command);% I8 E y, A+ C& Q' c- W9 R& A3 K& L
- $res = $result->toArray();
: A8 ]2 r: f8 @8 K& J- W j! {( Q - $count = 0;& z3 r- |/ w+ S$ P7 Z
- if ($res) {
* l( B3 T4 I7 a - $count = $res[0]->n;
% E3 z3 }# `' C, r- ~! z# k - }
2 Q7 Z' c0 y- H0 c6 U& ]8 u, i
' Q. M3 f$ S1 G9 ?( U/ ^8 W- return $count;
* ^' o% J) I! O- `" V - }& H- l5 W2 s3 n: W" W* S
- * S6 n3 | _: `# q% d% x2 B5 L
- public function update($where = [], $update = [], $upsert = false) {
5 V3 |9 w& E2 k- j - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);! K. G( |$ [( G& a
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
, x2 P7 O6 {$ g( u9 S
$ I, l; U1 ~+ K1 E. W- return $result->getModifiedCount();
9 o& K4 x. Y0 N- ^% I, O( {- g - }
, M# H8 u& E$ Q! { ` - 9 [$ F( A0 S0 {
- public function insert($data = []) {
6 r1 n' {" @: ~1 c$ B4 M, \ - $this->bulk->insert($data);
5 \2 x0 e; r6 P* L* s- s7 D - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);* j6 P0 ?* _* c7 ~/ h. @: ~3 _
0 U! N' J5 A$ `9 ^9 b- return $result->getInsertedCount();) ?' w. B# s: @* D
- }
9 ^7 I) X' g9 H* O' e5 R5 g
0 n9 H4 k+ M: s% N" t% O- public function delete($where = [], $limit = 1) {% ^ @2 u, U# y# E$ S/ p: W
- $this->bulk->delete($where, ['limit' => $limit]);( g" D9 {* e1 |' a1 ^' w
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);8 y: r) w( r; W' u3 S- r& c: M: ~
- : k# U; s0 y7 I0 o n& Q! F
- return $result->getDeletedCount();, [/ f H; G$ u& q2 j8 [
- }& a/ @% q6 |6 r* ~, K; w) @. J. z1 N9 Z
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原, J+ w& Z% H \9 N0 ?6 D. l
- 新" [1 K7 [) U+ L5 F S5 E+ {
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单' t: B0 V( n7 i$ x
- $lastId = $resultOne->getInsertedId();
$ t+ j' u. O7 I: a) i7 j - $resultMany = $collention->insertMany($array, $options);//多
0 f5 t4 W% Y0 B5 A - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原6 E _1 g# s3 E9 V+ _* B' a6 u
- $collention->update($condition, [0 m% p2 K* C4 W* r* u' @( B+ `
- '$set' => $values* w$ M1 g2 P" T8 q b
- ,[
! W' m0 F% I& V3 ~ - 'multiple' => true//多条,单条false/ y* e8 J2 B+ ^0 U
- ]);
复制代码- 新4 j7 j; O, E' T! q9 o/ {
- $collection->updateOne(2 z5 e# G9 E- G0 i
- ['state' => 'ny'],$ y @7 E4 c' T( o. w3 v; R3 W0 k
- ['$set' => ['country' => 'us']]4 }) w. g( }+ N6 r
- );9 @- ^+ D4 e0 s1 \
- $updateResult = $collection->updateMany(2 N L2 u. f9 y. g0 E. I$ ?
- ['state' => 'ny'],
, K4 _: Q) F+ g, i! l - ['$set' => ['country' => 'us']]
/ ~% y6 | I4 K5 P, h5 W - );: m. A/ k$ }( @5 O
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原) L u( g5 M( c( h1 I- A( q
- $cursor = $collection->find($condition, [
4 D0 Z' D( n& ` - 'name' => true//指定字段1 ^( p4 c7 O4 D/ J/ B
- ]);
' _* Y9 G5 c# `/ ]3 ^1 x" Q - $cursor->skip(5);* v/ o' i$ l- b; N) u* i- M
- $cursor->limit(5);/ k8 A4 b6 _6 u, n. ~
- $cursor->sort([. i4 ^4 N4 i$ _: K2 Z
- 'time' => -1
3 e) x( j9 S! t - ]);
复制代码- 新: Z9 Q7 y; ]& p _6 J( F- Q
- $cursor = $collection->find($condition, [" c1 t: T0 u2 F: E K' q i6 q3 R
- 'skip' => 5,
# J; ^' x- K4 H+ e" }# M* ]6 l - 'limit' => 5,0 P! ?0 L6 f+ _" M( y2 u4 J; _
- 'sort' => [
! c% n+ N" `8 R1 N. m* n - 'time' => -1( V; U, e5 C# e: P6 @; h
- ],//排序, [3 `$ `0 c% l: T# r
- 'projection' => [2 i( f* V5 n$ o1 O
- 'name' => 1//指定字段
, F( d8 \- h: U9 L- q8 j0 @. E - ]
5 u) \' X+ ~+ j3 t8 c5 S; w - ]);
复制代码 5.删除- 原
& M& { B7 w5 o8 ~% T1 U" r
- $collention->remove($condition, [
) ?" E) L1 \' Z - 'justOne' => false//删单条3 S1 e% B7 I) F; {- y
- ]);, e/ V' y7 u- |# }
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);) }( U" P) q: Z5 H7 [7 x/ x
- $collention->deleteMany($condition, $options);
% p! i; c5 n3 G+ q/ v* v
, m6 z) D. E+ b4 x& H. N1 ?- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
4 ?- Y/ r8 I& r - '_id' => $tableName//我在自增表中用其它的表名作主键
" J% k' e% Z3 c( d" O3 ] - ], [
5 F+ U# u: x% n: V! ` - '$inc' => ['id' => 1]//自增1 X) n7 f" _% C F% Z
- ], [; r' K# }' ]" z7 z) X6 F! R# [: Z
- '_id' => 0. |. K# L1 Z) h
- ], [
0 N3 o+ r$ B7 g. ^: O - 'new' => 1//返回修改后的结果,默认是修改前的( U5 P8 n, N; ]* W% O
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([ E" P6 J5 v" o$ G) j- c) Y
- '_id' => $tableName# `5 @9 @: f5 b& j- p: P p& V! [
- ], [! R( I7 g* O9 Z/ [9 M
- '$inc' => ['id' => 1]+ w5 t! ]5 ?$ t9 t" i! P( a8 v
- ], [; w* P+ X& `$ v$ L9 H2 h( b. |
- 'projection' => ['id' => 1],% ?8 E) c1 ~/ U5 l# L5 X
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
t, O$ C3 I* t4 w: ]! i* ^4 U - ]);
复制代码
6 [, H, b9 A" [& ^* h
/ D/ W3 Q) _5 b+ k! L4 I: A |