使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php$ j6 C% R" Z8 e( O3 q0 q
: W7 S' M! W) Z# u( K0 N3 E- use MongoDB\Driver\Manager;3 t+ Y/ S7 c% B V
- use MongoDB\Driver\BulkWrite;3 b# N* b! J' T# ^ c
- use MongoDB\Driver\WriteConcern;
& v4 S! b8 k. N9 I7 i" l - use MongoDB\Driver\Query;
3 |! i& j* W* U& |* q1 I - use MongoDB\Driver\Command;
- u- O. d; o1 N0 l - 9 }2 y2 ?7 g9 u0 [! Q- f
- class MongoDb {
) R8 }: r& a- k% k* V0 T - 1 e, {. ^4 P7 h. @, V0 [
- protected $mongodb;
: s# N( r6 e) I) D - protected $database;7 b+ O& x" D& t+ W3 C& Q: X
- protected $collection;$ ~* b+ m8 G" j: E" X
- protected $bulk;' r! \5 @ c4 j: U* q' |
- protected $writeConcern;% t# y0 W% ^! _' z6 Y
- protected $defaultConfig
* p" x. S: Z) f$ `) _3 k - = [
5 Q: l$ V, o2 X2 h3 N - 'hostname' => 'localhost',
+ I# `2 i4 d, N& D' X1 h* u% o7 \ - 'port' => '27017',. S& l- o$ G! s0 h
- 'username' => '',
' z ~- E7 P- J- l8 l, a7 c - 'password' => '',0 P: f9 ^/ ]4 K, N9 T6 p) e$ V
- 'database' => 'test'
6 i8 Y7 ]! l" a: r$ u. O/ ? - ];
$ h/ J3 k- O* d, D - e9 [' U# z- m( C* `& {! r7 [& j
- public function __construct($config) {% ?& S8 G: P0 ~& F
- $config = array_merge($this->defaultConfig, $config);
9 K) p0 F/ \2 b. |0 N& Y) n v - $mongoServer = "mongodb://";: q7 B6 `' |! m4 Q
- if ($config['username']) {
1 i1 g- k/ O- T+ C: u4 k( W8 z* q& B - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
& F, L/ M. c0 x2 n4 ~ ?% m, Z" \ - }8 C- Z7 s. o- M
- $mongoServer .= $config['hostname'];
! }' S& t4 \: { A - if ($config['port']) {+ u' J4 Y( ^6 l) B
- $mongoServer .= ':' . $config['port'];
4 n# b( e% r" q* h: X - }3 p% g4 d+ c" U, `5 D* Q
- $mongoServer .= '/' . $config['database'];
" l+ g2 `* `) e2 R E
3 p, f7 e8 q; |9 _- $this->mongodb = new Manager($mongoServer);, D2 M6 I% @2 }7 p7 F3 g S. Z3 t: {" B
- $this->database = $config['database'];
P$ G# i5 `; o/ r5 ]) s% G3 W - $this->collection = $config['collection'];
; H' E K3 m/ G" D# l9 P; S9 i - $this->bulk = new BulkWrite();
/ c$ ^* b/ f6 D& } - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);( Y# d! e/ m# B" ~& a/ X5 Z
- }
# G% G3 M% R) q0 S1 S) G5 f$ a. \
+ a6 e; T' q1 @9 O( l- h H- public function query($where = [], $option = []) {
# s& k P! _- @) M9 }8 }: i - $query = new Query($where, $option); o0 {/ m* c3 E; ` [8 @
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
9 b7 _6 F; @/ ~ W! B- @' l; T
- l& R4 F2 P% B8 B, g9 Y- return json_encode($result);
- e. ~0 e+ g) @6 |% `. W - }# f# Z# U* J; A; o8 {/ D' [
- ! q- K2 S1 d' h, p5 j& _9 K
- public function count($where = []) {7 d$ b6 P1 O# a0 d( ?, O
- $command = new Command(['count' => $this->collection, 'query' => $where]);! q4 U$ \: n6 o1 h: q
- $result = $this->mongodb->executeCommand($this->database, $command);
; e3 y& C! z" J - $res = $result->toArray();" M8 S. J: s' d& W1 s: ?
- $count = 0;4 l' J. H% A1 e
- if ($res) {* Z7 [5 G) s1 [( m
- $count = $res[0]->n;
, ^- M4 w; ?) X- s; U4 @ - }
8 q* i% T, V; h3 X8 b9 U6 n. A' c
0 @- P; T' ?" T2 x- return $count;
, s% C9 r% E; G$ Y - }0 D! Q. ?1 X( B) l" T- ~
8 V6 u$ D$ a8 w" V# I- public function update($where = [], $update = [], $upsert = false) {
* G- X# C/ u( c - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
4 I* E& N1 {- ]8 ~" @ - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);3 `/ \# q# O0 g" f% P
% i% ^0 D0 g2 c/ E2 n- return $result->getModifiedCount(); C7 ]8 q( F Z' S$ R+ J( V' N
- }6 P) P9 E+ y5 f* A5 l; [" x ~
- & _4 P5 v' F2 g L9 m! z: \; A# m! M
- public function insert($data = []) {: t7 h' x* ^) f5 g, B
- $this->bulk->insert($data);9 [& `' e) \8 U, {* W7 b2 X* B, s( X5 |
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern); U: I2 A: I# ~9 S( e) n# f9 t
) S& U/ K3 c0 o) q" O% w# ^- return $result->getInsertedCount();1 z) T3 W ?8 N. [4 R4 l' b; s
- }+ R8 V9 C9 `$ o% {
- . ?& ^1 L* s: G9 U* o* N @! V/ j
- public function delete($where = [], $limit = 1) {- t* I" D; H! `& P% S9 h# X
- $this->bulk->delete($where, ['limit' => $limit]);& U8 t" L0 a* p
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);6 T4 Y, ?0 N) s1 L ^4 ^: M
- . q6 }* c. o/ ~6 u$ n
- return $result->getDeletedCount();8 s! i4 F! v' {! h
- }" Y2 |" V9 K2 S3 R! T0 `
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- 新% D6 i6 v' A' c4 t, G& M" A2 @
- $resultOne = $collention->insertOne($array, $options);//单
6 \2 ?6 ^: _; ?% ]$ a - $lastId = $resultOne->getInsertedId();
+ p! {- S! F, x) ] - $resultMany = $collention->insertMany($array, $options);//多% ^" B% L" N) P( y( V- F
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
) z7 ^3 R, |; C5 P0 I9 N
- $collention->update($condition, [/ ^ U2 v3 {$ W3 H" g" u4 ~0 x
- '$set' => $values' o3 {+ P: I5 J: y: s2 C, F
- ,[
) a& }$ h k9 N+ M. I - 'multiple' => true//多条,单条false
# N' D; O6 q% s7 ^9 C9 W - ]);
复制代码- $collection->updateOne(
1 s& n/ n3 l, e - ['state' => 'ny'],0 f$ O7 ~2 o! W% T
- ['$set' => ['country' => 'us']]
% o( t- \6 e. {+ h- b8 G - );
# `/ H9 N: W$ g7 c# R - $updateResult = $collection->updateMany(* x7 f( h2 C) O
- ['state' => 'ny'],& U6 e% T/ T5 ]* P8 w' z4 g
- ['$set' => ['country' => 'us']]/ [* _, E+ l" c3 W
- );8 Z* x- Q+ w" W; ^& N& h+ s5 o$ L
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [; ~5 g( {) O: u+ U
- 'name' => true//指定字段
+ F$ y' s, e: r1 e% M - ]);
) j' Q+ i( y6 w- J, A - $cursor->skip(5);. O7 t7 @7 w V6 q* L; }* d
- $cursor->limit(5);
8 C1 f$ S5 I" {% H7 U$ T - $cursor->sort([* p# B" r. z A6 l! c
- 'time' => -1/ n1 A- K% w: q! [9 C
- ]);
复制代码- 新: Y' }; k- A+ E* l% \) x
- $cursor = $collection->find($condition, [2 J( V3 R0 P o& k! M7 }) ]' _: S
- 'skip' => 5,6 e, w) M3 D3 u( i5 e
- 'limit' => 5,
. U( A2 ]; X- h" |) c$ A - 'sort' => [& S" x/ x- T7 ]4 ]0 p
- 'time' => -10 o5 d; \" m4 F
- ],//排序
7 e- o2 M! \/ F. a* k9 _/ f7 f! o - 'projection' => [
) x) Q2 h" ]$ @. g- u6 K- R - 'name' => 1//指定字段
, f0 g/ J2 M+ a# Y6 _5 \ - ]
2 t$ z* @, W x( W8 N3 J - ]);
复制代码 5.删除- 原" Z! M( R. h- e+ O7 t* k$ _
- $collention->remove($condition, [: c$ i% P, z) X+ L p9 o( a {
- 'justOne' => false//删单条
+ H# s" j O+ [+ z S - ]);6 k% {+ G: |, s5 B
- $collention->remove([]);//删所有
复制代码- 新# J- U& N+ y) q* ?- L m* ]" o
- $result = $collention->deleteOne($condition, $options);. R' K. S( F4 o1 ^7 _. [
- $collention->deleteMany($condition, $options);
( v3 |6 M! s5 y: g+ K( u5 q
% F/ U4 J% v7 `, v* X$ Q- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
# j. b! d) x# T: h# G" B( }+ H - '_id' => $tableName//我在自增表中用其它的表名作主键: }$ d/ k6 @* c3 O. ^% |8 e
- ], [9 u5 v% c% r4 t( ?, q/ d- }9 e- U
- '$inc' => ['id' => 1]//自增
! x% m/ }0 y, I - ], [* F7 E T* @' q
- '_id' => 0/ g4 k' V/ K% Q, e, B
- ], [! `2 l2 E8 H' ^. F
- 'new' => 1//返回修改后的结果,默认是修改前的
% J9 U/ ^4 \" F h - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([1 [: Z' G1 O& f+ D& @2 n4 l2 R
- '_id' => $tableName% D, N; q9 w4 L9 F1 p6 w
- ], [
E% H, _3 k, }6 w! P$ G - '$inc' => ['id' => 1]8 a1 b Q5 Z# [0 O9 t4 I
- ], [- ], a& m1 I3 f" ~& f( |/ f
- 'projection' => ['id' => 1],
! z; \( Z% ^/ X/ d! ` - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER$ s' }5 {! o% U, P2 |/ a
- ]);
复制代码 0 w/ X4 W; c. V+ g
; |! x5 x# ]: e1 ~ C' H |