使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
& A, R2 u/ M6 _ N4 k - 5 ]4 Y, |( C# o2 X# o- N
- use MongoDB\Driver\Manager;
1 b& N9 ~- j4 X _2 I- D - use MongoDB\Driver\BulkWrite;
% f% L. ?' L$ R4 H - use MongoDB\Driver\WriteConcern;
9 e' @, b+ _# ?& N# u/ @/ y - use MongoDB\Driver\Query;0 E" Z& d {& [
- use MongoDB\Driver\Command;, ?" R- f# B; X" Z' _
: f! J6 d. S# p! i- class MongoDb { A( n8 D. ~2 _1 u8 y
5 Q0 C7 M V) Q6 J- protected $mongodb;, z2 \7 g" _( m+ I# ~" n- F
- protected $database;8 Y) D& Z: W8 n' f' z# Y
- protected $collection;
# }" P* ^4 F4 F Q- s - protected $bulk;4 o) Z7 h9 l+ N2 o+ F, ?6 f
- protected $writeConcern;' f8 Q+ Y0 f& Z) L }4 D! ~
- protected $defaultConfig& W+ P1 v' b# |! g3 d
- = [
9 Z# Z/ Y& `0 @6 H* Z. G) g - 'hostname' => 'localhost',
( J7 u$ g3 C; T - 'port' => '27017',5 I$ d8 U t% {4 s" r( R5 J* G
- 'username' => '',/ V9 B# v7 }, h" f6 F, ^
- 'password' => '',
! y) F" @8 ]# y7 l5 C8 N! f6 p( a - 'database' => 'test'8 ^$ J- J( r, w) \4 [/ O; Q+ ^1 `
- ];
$ q) [4 ?# ]/ @
$ c; |! }- H2 S1 c) O- T- public function __construct($config) {
u- H, ^# [7 f* J y2 B% ` - $config = array_merge($this->defaultConfig, $config);
2 h% Q0 Y) l2 Z - $mongoServer = "mongodb://";$ H4 X* ^, ?4 ^, }5 Y
- if ($config['username']) {
" E3 b- b2 @8 N4 }6 U( Y - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
) H& A+ U( W# x7 T. A$ }) r - }
$ ~! ?- Y6 J2 x/ t - $mongoServer .= $config['hostname'];/ H& U; t9 K* ?1 Z4 b1 r
- if ($config['port']) {
) g" o, p/ l- ?8 ^) |/ X" p - $mongoServer .= ':' . $config['port'];/ E, O7 W ^8 E8 }5 {
- }
# e& o6 X# ? I% |) u% s! _1 J - $mongoServer .= '/' . $config['database'];
7 f" e+ [+ B2 E: l8 ^) i2 {
) G' D2 R: E, H6 o' S6 B- $this->mongodb = new Manager($mongoServer);
0 H( `- e' F; Q t7 ~& K - $this->database = $config['database'];
9 g& T/ f* t" v4 f! F - $this->collection = $config['collection'];
! T. F3 }# M8 f0 h6 [1 g& _ - $this->bulk = new BulkWrite();7 O) ^- \' z# ^" F
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);' z6 b7 m( H8 w+ m' J
- }+ j: S2 S, b% s) D* _
- * P- c4 z4 }% U3 F. |; e
- public function query($where = [], $option = []) {6 x; y9 w4 `' X- m) q* S! t
- $query = new Query($where, $option);2 |$ b# X8 b2 [5 A% T
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);2 B1 k: _: t. [$ ~
( q0 G$ J8 {, z' s- return json_encode($result);
% S4 ], M- e: P5 L - }
* y# h2 ^- l) x+ _ - / Q$ ^( Z, d0 M
- public function count($where = []) {5 X% _2 w8 Q, Q* i! K1 W2 B7 |: L% h
- $command = new Command(['count' => $this->collection, 'query' => $where]);
) h. l1 L: I+ D' b0 f n2 s - $result = $this->mongodb->executeCommand($this->database, $command);
) i; z' P3 Q! ?. h9 S& A - $res = $result->toArray();
! d5 ?. r" P& }! }9 q7 r - $count = 0;+ |4 `- M! ^6 r6 `
- if ($res) {7 J5 G F C# {; G$ S! U
- $count = $res[0]->n;" [7 {8 U! D1 q5 I- P8 \
- }
. Y$ r0 k' b0 k0 J5 { - / q/ K' z# T4 G ?( m! a0 G* f
- return $count;
: i6 E4 Z( {- }' g" w - } Q: u& r5 y5 p6 g$ W
" y9 J4 y+ S/ m! m- public function update($where = [], $update = [], $upsert = false) {* I* O: _/ ~3 c0 k6 f
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);/ z0 I& [- q5 j0 a
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# F# ^9 _) ?$ q1 }: p$ q
- ; F0 C& V! @. y# z e5 |0 @3 [
- return $result->getModifiedCount();
2 y: t H# v5 M4 k - }4 x2 W2 P6 }1 Y* x! u2 g# M! }# f9 i
- 4 n+ m/ h5 E5 _+ K& o j) K* o* ]
- public function insert($data = []) {) K9 n6 b9 k# T/ z! d
- $this->bulk->insert($data);. F3 t9 v( v& k
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
, b5 p8 i/ s7 ` r7 y - " Z- ]) B0 @9 Q8 h! R
- return $result->getInsertedCount();- _ I9 O8 W; c
- }' \. d/ x' a- h, s: G" e( u9 k
- % T( W! }6 h7 l' g
- public function delete($where = [], $limit = 1) {# Z S7 }$ ?* Y* x
- $this->bulk->delete($where, ['limit' => $limit]);
; Q7 L* f7 x; l4 r' d ? - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);/ V( s. \2 E& z) H
$ F" \% z1 K- C; W% W- return $result->getDeletedCount();5 |4 U O# e1 o* g6 N
- }3 m. h8 ?) q1 R! x" q
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原
9 u( S5 B! d, F; t. P) M r! K
- $collention->insert($array, $options);
复制代码- 新 U @8 ^5 x* p7 K r( @2 m" x3 w
- $resultOne = $collention->insertOne($array, $options);//单
/ W' K u9 k/ J. Q! a* b5 c! B - $lastId = $resultOne->getInsertedId();9 m( K3 |( ]- [) K
- $resultMany = $collention->insertMany($array, $options);//多! N9 K3 k, v. g Y& w9 c8 q
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原5 t" r$ i8 g1 u3 K, v7 M
- $collention->update($condition, [
, a3 D0 a! }# A6 i$ t7 F - '$set' => $values, X% [4 b3 c+ D/ E
- ,[: V5 X, a8 V) O% Z
- 'multiple' => true//多条,单条false
1 d/ _0 W8 {3 q( H. `" a# @ - ]);
复制代码- 新/ k1 e, `; Z' r2 X" \/ ?% r% v
- $collection->updateOne(
0 R F: G5 ?# S+ C9 N2 Y - ['state' => 'ny'],
l$ }8 M; l# K- X/ g8 k - ['$set' => ['country' => 'us']]
7 I5 l# W/ y& n - );+ G8 {- w' ^- W
- $updateResult = $collection->updateMany(, S _- g8 r4 A8 S. c3 S- c. W
- ['state' => 'ny'],
G" U3 G+ i7 @/ ] - ['$set' => ['country' => 'us']]2 X- q9 m6 O' i1 U/ {" B- ?( k
- );
" E+ ?7 P: v7 J- @ - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
' p4 I+ C+ A% A& f, |: J
- $cursor = $collection->find($condition, [$ `; d: i/ n, y; s) O
- 'name' => true//指定字段$ R- ]: M& ]* I
- ]);# S: e8 L- o. Z4 l4 {) V+ E
- $cursor->skip(5);
& f: s& G* Y' ^$ _4 h) Y - $cursor->limit(5);
3 F- {* [: X8 P6 D2 k - $cursor->sort([" C: `8 B ]( Y! K+ \! o, Y
- 'time' => -16 E/ H8 n3 w) f
- ]);
复制代码- 新8 w0 g; m% h+ X1 U% E3 }
- $cursor = $collection->find($condition, [1 ]0 o$ p) G; Z" W/ p0 E
- 'skip' => 5,
6 g( Z3 C0 b2 r+ W - 'limit' => 5,
# H5 G3 u; f( B$ f& ~# [( i - 'sort' => [9 e. e; n& x* P% ^% `( A% o
- 'time' => -1( |8 c( r6 G' P; G% y
- ],//排序2 ?( ~2 b$ l$ I5 |( v( y
- 'projection' => [- Z% G9 T! Y! |9 ^0 ^
- 'name' => 1//指定字段& { W% ?9 c7 F# r3 D
- ]
4 s( j' G2 R# a* C% e - ]);
复制代码 5.删除- $collention->remove($condition, [
% K! y! q' k. T( F; \ - 'justOne' => false//删单条/ Z u7 E0 J0 `; A
- ]);
4 o" k; g8 L* }5 w+ t3 b$ M3 _ - $collention->remove([]);//删所有
复制代码- 新" b" s. Q7 L# p. m0 w3 }: J
- $result = $collention->deleteOne($condition, $options);
& ?, T# H5 C" L; F: f - $collention->deleteMany($condition, $options);
0 ?& q# l9 E# O2 s/ S% L* m, i% A2 W
. k( F& i) h; G2 d- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([7 @3 V' b8 K) E0 o3 Y
- '_id' => $tableName//我在自增表中用其它的表名作主键
4 ^6 I" t! g2 M9 G7 ?6 I! Y/ M - ], [2 G8 l8 ^% h' G, v- l2 f+ A9 ~
- '$inc' => ['id' => 1]//自增5 V6 g2 `. i7 j/ C
- ], [1 S8 Z. Z) E# @0 U0 ?& |
- '_id' => 0
8 m7 y$ ]6 y& e, h- q2 p - ], [
7 }% g2 u5 A1 m1 p7 n - 'new' => 1//返回修改后的结果,默认是修改前的9 K' }1 {( d( C, V
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([. c+ ]! Y' d D% N$ _/ W1 w7 M+ v' {
- '_id' => $tableName8 N+ p" V/ ?; f( B" H9 S% M4 @
- ], [
* M3 n+ e0 i7 p6 R0 c - '$inc' => ['id' => 1]: i& x5 O! O8 F4 v- E, Q2 A% T' v2 G
- ], [
# M. g' P; h1 A - 'projection' => ['id' => 1],
) H. D& j$ H% M/ p - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
' E! _% u) r% F4 Q! ?7 m* f' h - ]);
复制代码
! l* r2 j$ C, b6 c) X' }- E0 K7 e6 Y' ~+ F
|