|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php# t8 I( l" ?: @
- 9 n$ O7 M. b+ t; q2 r( o: w
- use MongoDB\Driver\Manager;
6 G" A% T4 j; }6 g/ l7 J! g - use MongoDB\Driver\BulkWrite;/ ^7 V3 I( e& `, q
- use MongoDB\Driver\WriteConcern;; n: |9 u% f ?& ~. j' M7 q
- use MongoDB\Driver\Query;$ W1 n6 D" H( o) Q
- use MongoDB\Driver\Command;& A& v1 c% y6 z7 u; Q% ?
- ; z, X& S* p& a9 H
- class MongoDb {
/ L) h1 r3 P/ R7 J! Y2 h - 2 J6 b/ s4 B% ?/ M) Y. D
- protected $mongodb;+ j/ @$ W5 C4 l6 e A+ W
- protected $database;) g: M3 e5 g) ?% x
- protected $collection;
& t9 s( @6 W" `9 X7 I: R9 @5 s. b" r - protected $bulk;) d" @2 Q: {9 V3 d
- protected $writeConcern;5 Q0 b& Z% P8 q* |5 X9 s
- protected $defaultConfig
6 X! _7 h" N7 C& {% q - = [) t& v9 X' E/ w( z
- 'hostname' => 'localhost',
3 w, e+ b2 C3 V: H6 y3 y- T5 j& l5 A8 k - 'port' => '27017',& E0 P, y0 z2 t' M% m& K* I
- 'username' => '',9 L4 d2 e, u4 v& _; }+ t
- 'password' => '',
# h2 ]8 [' o" k0 r. d+ {4 R - 'database' => 'test'6 v* w8 D" r+ q
- ];
. L; p; O6 W, E5 t: d# ]% d8 K - * d' T3 P) k9 h# m$ O8 h3 ]
- public function __construct($config) {
8 l) M9 Q. d' A - $config = array_merge($this->defaultConfig, $config);
) i' b9 P. {5 k/ c( g. D: H" ^ - $mongoServer = "mongodb://";
0 U/ t" L4 i4 a8 W- j - if ($config['username']) {( B8 l6 W8 }0 p+ ?2 o
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
( v/ S1 y7 u P) Z+ }) ~" s - }8 P8 H6 h$ T$ ~' a% X: H$ K
- $mongoServer .= $config['hostname'];! H* C3 y2 v" k2 F
- if ($config['port']) {5 g2 O2 c4 x3 E: |6 |/ Q
- $mongoServer .= ':' . $config['port'];) D; Y1 b' v; C$ q! Q/ ?2 r
- }: S7 G7 {' L4 c% n+ s1 n# @# {' C
- $mongoServer .= '/' . $config['database'];, l9 J L- ?8 F! X! q" `+ Y" c
) n" r( n/ k6 j. @. B8 M( D- $this->mongodb = new Manager($mongoServer);" D' s) y, U, Y, I3 Z" K' v
- $this->database = $config['database'];
( H" C$ y% @1 l* W - $this->collection = $config['collection'];1 b% F" N. J. ~' N+ N+ @, K
- $this->bulk = new BulkWrite();6 k" k# p- x% U
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);9 ?1 W9 J1 l( l) c" L1 Q6 ?
- }2 u' s/ x3 ?' i
- 7 |% z c" j$ }+ z% I
- public function query($where = [], $option = []) {
- I1 U: f" `6 B: h- t - $query = new Query($where, $option);
% E+ Y1 k6 u- X: q. } - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
. B7 g% j2 h0 G - # D' S; s# b" l: Y2 u2 z! O
- return json_encode($result);
, }7 @3 l% W1 r/ H - }3 A- e# F" b# x# n& ]
+ s2 w/ m% I% ]* o+ ? k6 M6 p- public function count($where = []) {
s4 T2 K/ W8 Z( e: `! T" z, t, y - $command = new Command(['count' => $this->collection, 'query' => $where]);
, x6 z% M# g# A7 d - $result = $this->mongodb->executeCommand($this->database, $command);9 v0 X8 K. t* l9 m' `/ B
- $res = $result->toArray();
& P f$ g2 ?' B/ L( ] F& y4 j2 u - $count = 0;
# s1 K# B$ i3 H9 k S - if ($res) {
& l/ }2 _ n$ H3 R1 B1 W4 | - $count = $res[0]->n;
; n* f. A5 ^5 p! C- P7 n - }1 G( ^0 ^8 k1 b; {/ K
% t s$ \ L4 Y4 E) m# G( U- return $count;
& c% W/ P- N8 c' J - }9 V6 L( O% L$ B( K% J/ ^7 f( {1 T
6 {9 g% e8 l6 Z r9 U$ }+ r4 @- public function update($where = [], $update = [], $upsert = false) {
* Y: g/ B0 L$ c4 r1 I {7 Z - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);9 y) p* K H! ?' F1 I
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);; H. c, U# Z& M
- ! \+ y: S* V' }: v; f* L
- return $result->getModifiedCount();
+ m9 q; s( }: Z- @ - }( L, E& X1 A" D) L. a( {
- , v% _1 S. v3 ?# _0 t& A
- public function insert($data = []) {& C: D& n/ D0 x. R! i' o4 G
- $this->bulk->insert($data);: d( O. [% ^; b/ Y
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
H" `; m6 x( ^! U. R& I0 f$ ? - , X+ Z7 O- @" k* x0 ]) c; [
- return $result->getInsertedCount();/ q% e. U; J$ Y5 R, a, F
- }$ ^" I! n4 f9 |2 J% J
- 1 ^9 K3 f" V, d1 h5 X6 Y( |
- public function delete($where = [], $limit = 1) {- M; y! x, k% O3 ^
- $this->bulk->delete($where, ['limit' => $limit]);
N0 U. W+ `- k l3 F - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
2 Y% s* S/ ~' e1 j) H) Q8 P* ^ - ; f& P% M" ]6 E/ q) D2 i& K& i' Z
- return $result->getDeletedCount();
2 F3 r% w* {6 I' s - }: F9 H9 ]) L# n% y6 E
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原0 s5 b4 n! y% }2 X7 m; {1 L
- 新
* |2 F& c* ^6 Q' o$ P3 g" m4 |: h 2.新增- 原
; I" a0 X/ T8 ^ j8 T: l- l( }( p
- $collention->insert($array, $options);
复制代码- 新
9 _4 @; |7 \* W/ o+ _$ a! T' e
- $resultOne = $collention->insertOne($array, $options);//单8 I8 \! w$ m5 q/ w
- $lastId = $resultOne->getInsertedId();; z D: P) V) Y8 H j+ W3 m
- $resultMany = $collention->insertMany($array, $options);//多
( M4 e* z p# m7 L6 H% Q2 ?- |9 g - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
. i4 ~# z- R; t" M3 B" A
- $collention->update($condition, [! X6 i# b2 x6 _9 B
- '$set' => $values; {9 Y0 `4 K2 F1 d4 O' f+ y
- ,[! _3 y) B5 @0 ]* F5 V
- 'multiple' => true//多条,单条false
% }) o$ k, Y/ {6 @5 O, \4 E: M - ]);
复制代码- 新' {6 a8 A+ h; k. v4 D$ i
- $collection->updateOne(6 r3 g# O" Y( J: ~# t$ r3 ?
- ['state' => 'ny'],
$ I$ K. F9 S) b' c - ['$set' => ['country' => 'us']]" r+ T9 p* M0 W% d) H. h! v
- );
, c* o6 y! m7 d0 I - $updateResult = $collection->updateMany(- z: O2 | x) y5 D
- ['state' => 'ny'],# v3 c8 j0 b4 n+ p
- ['$set' => ['country' => 'us']]
+ V& v6 _) c: L6 ]: j/ ~, s! X - );3 L" U; z6 R& q c! i8 P. }' N
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [2 o6 A$ H; ^& ?5 _; \7 _8 u% I5 s6 P2 f
- 'name' => true//指定字段; A% p1 `+ s) {$ d( x
- ]);
2 e: s1 a5 d5 ]2 x' \ - $cursor->skip(5);
3 u' L( d! F! G! m8 @: b2 x - $cursor->limit(5);
. M+ k0 K" W4 w - $cursor->sort([
$ d3 L7 e+ A% K/ u! K6 T - 'time' => -1
2 a5 Q" P$ R9 e1 v5 o6 e- \6 c- P - ]);
复制代码- $cursor = $collection->find($condition, [1 p! C- k; _8 ]# e6 x* G. i
- 'skip' => 5,. r7 a( b* P( r2 B$ m; q
- 'limit' => 5,
1 j& ~" g3 N) h2 {! ? - 'sort' => [- n. F) Q9 i+ U( a$ Q4 T
- 'time' => -1
+ k" E0 P8 u- N' D) S, }: J1 \ - ],//排序. H. k2 A. y* q. i3 B( R/ f" T/ {
- 'projection' => [
. Y- ` [6 g1 ~9 N - 'name' => 1//指定字段, q* i& s& t2 B2 K5 D/ m4 }
- ]
/ j, ]- U, A, F9 M0 E) s - ]);
复制代码 5.删除- 原
) b! B1 y: Q7 R+ P$ ?. J' ]
- $collention->remove($condition, [
3 R0 _7 \" F2 O: y# E& ^2 R g, y - 'justOne' => false//删单条) a) G6 S, I" `9 {) M
- ]);
j& i5 R) Y! S6 K$ t - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);% M6 Z5 T: _7 d- _, a0 l! E3 N. z
- $collention->deleteMany($condition, $options);& n5 }. n5 h' I% S$ l$ k8 u+ L6 O
6 y( t/ l; Q+ b. h6 F- T1 n- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
. N' P0 x' P; @ - '_id' => $tableName//我在自增表中用其它的表名作主键
- r4 U' T# h3 ? - ], [
: [: o6 e" }" B7 r. D& o: v4 P - '$inc' => ['id' => 1]//自增5 a* S! t" o7 W0 b
- ], [ i* u# ]( C- r8 u# O. O o
- '_id' => 0" |) X: D1 G- R% v& l4 h( y4 q1 {
- ], [
0 K7 [+ H; i; i1 i: h) h4 ~ - 'new' => 1//返回修改后的结果,默认是修改前的
: d& u2 ~7 t5 m, L; S2 ]1 P( }% N( k9 V! B - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
& y$ v8 f# `1 L% E, Y+ V% |! R1 o) i - '_id' => $tableName
4 q; b. m3 |4 x - ], [
- E) P* P$ y: S, l( z, E. @ F - '$inc' => ['id' => 1]4 X$ }( V. D* ~1 P& H4 z
- ], [4 i* E, K9 E7 ^) P6 e1 B7 u
- 'projection' => ['id' => 1],
# }6 J( G3 {6 h - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
- P4 m5 B5 \3 _: s2 R9 H& C - ]);
复制代码 8 n) a( K% ~# Y. Q
/ m. X' ^2 D5 }7 ?
|