|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
5 h3 b/ C! b" Y' A
" K3 P8 J ]: p) q- C( o. V- use MongoDB\Driver\Manager;' A6 n+ k% I0 u/ r3 h( s
- use MongoDB\Driver\BulkWrite;
2 h; h/ L" j% H$ K+ ~" s - use MongoDB\Driver\WriteConcern;
7 c/ F. L9 Q$ a& G! ?2 r - use MongoDB\Driver\Query;
8 G! j2 s- `* C. b p/ Z; r - use MongoDB\Driver\Command;$ o* h/ Y5 @! d' C- B
; X2 U- L$ S: \% w) N' U! P K- class MongoDb {; T& M; U- Y" @/ J) y3 e" r2 e
- 3 z5 y& j! I; @7 E% E
- protected $mongodb;
6 p4 D. E$ R% p - protected $database;# }7 O2 |6 `: a
- protected $collection;6 [% C v' ^; l5 P" v
- protected $bulk;
4 \& v% l( H$ @1 v - protected $writeConcern;, N6 ^& y. D( V0 v5 G) S: K
- protected $defaultConfig( p! V0 h+ @8 m% A
- = [+ W3 j3 \6 C: E5 Z7 G8 A
- 'hostname' => 'localhost',- x! D; j4 `& `
- 'port' => '27017',- |: H: Z) U( B
- 'username' => '',
! Y# u6 v: s' F: i4 C6 c- } - 'password' => '',
! d) d4 O/ @' u" }1 L+ h* b8 A - 'database' => 'test'0 E6 {/ [: S# |, }& Q
- ];
+ n/ y! l( |3 y5 a# `% j
8 T5 V9 C7 y. [1 p! a' @) `$ I- public function __construct($config) {+ b( u* l/ _3 j! g, N
- $config = array_merge($this->defaultConfig, $config);9 m: z: w4 @9 P+ c# M
- $mongoServer = "mongodb://";1 b; e m$ m9 f; n1 v3 I4 K
- if ($config['username']) {1 K. U |# s, B% S
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';2 N$ r1 u2 `* i. `/ G
- }
" d5 u) }- }9 u- [5 K; E$ n - $mongoServer .= $config['hostname'];8 w/ X5 h, _( r* H; g4 a$ I; ^/ {
- if ($config['port']) {
/ ]+ ]7 @- c# k' k7 N! Q8 x - $mongoServer .= ':' . $config['port'];( l$ ~4 O* {/ g
- }
: w/ b' w; f8 W% D: M - $mongoServer .= '/' . $config['database'];
: a. M% g' q+ G. I
0 _& c1 l: a' y& X# {- $this->mongodb = new Manager($mongoServer);
+ s4 A# m6 P; o5 [4 `9 p - $this->database = $config['database'];
/ I5 l( S, e2 {' P - $this->collection = $config['collection'];5 X4 O7 S3 m; C D2 ~
- $this->bulk = new BulkWrite();
* y9 x3 A, U3 Y+ T2 _9 z2 h1 @% P - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);6 n; x5 y' q* d9 }2 l% I+ |
- }
2 b% h+ }$ p: T# N d W
8 T! `1 d' l1 p- public function query($where = [], $option = []) {
4 z# l' I2 J. v. Z - $query = new Query($where, $option); Q" p1 z# u0 u" u( h6 _/ o
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);5 n1 h/ D: f7 ?2 N
- " T/ {0 q! `5 @# M. w1 M1 A
- return json_encode($result);
* T* a. d7 C( m; i# k - }
; G! ^* z" w$ f+ O7 q
5 Q6 B3 N; E. M" L7 B* L- public function count($where = []) {$ ^8 F4 r, \4 g8 q1 \' l
- $command = new Command(['count' => $this->collection, 'query' => $where]);
9 o! Y% r) L/ r* I Q1 N6 F - $result = $this->mongodb->executeCommand($this->database, $command);8 r% v4 F# T1 Q2 R
- $res = $result->toArray();. f: ^$ Z4 t1 p4 \" s8 G3 k
- $count = 0;, f, Z9 _# W( d1 N. m
- if ($res) {5 p1 U( L6 L8 `
- $count = $res[0]->n;8 z' F p( Q5 @5 O- \3 V
- }
7 M7 o9 q2 W; B" B - * U5 x2 k- g8 G* v; p
- return $count;
- S2 \: N3 R2 T9 } - }% i# ^) _- b5 k
3 ^7 G* t0 a- S0 B- public function update($where = [], $update = [], $upsert = false) {
& B" h$ b) Y2 h: o8 Y4 L) S2 Q - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
4 X4 b$ a* \" W" Q6 d6 d - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
$ F$ i- N% B. g( j - : B7 w; ~3 O" ]" _0 G& y5 }
- return $result->getModifiedCount();
6 D n$ U/ B. E& M2 g! I+ H9 Z - }4 _0 w( R% O9 }% J# r
) W$ C/ ~) J) K3 v6 m1 B- public function insert($data = []) {! i! l: D7 S6 S
- $this->bulk->insert($data);) v, h2 T5 ~+ N( |# A% [
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);" ^3 c0 H- q) M! U) K: \& [
) m& @; J- C/ i: S J- u+ t- return $result->getInsertedCount();) u" C2 }2 {/ ?$ {6 Z) F1 }
- }
" c, v% t) \/ U( @5 b - |% V8 Y4 O( i9 w# ^! n, X, H
- public function delete($where = [], $limit = 1) {
, r! F+ d9 D# F6 y( _- J2 W# m - $this->bulk->delete($where, ['limit' => $limit]);, L2 {1 N8 W7 n* p9 g* M
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
# O! n7 ^. r5 {6 r, O( I1 \4 J
, r* w* w/ H7 n# B. j7 V, a- return $result->getDeletedCount();
1 W1 a' |# Y% ?5 y8 w/ B - }
2 t9 `8 G2 `, u6 t4 \ - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新! V; T5 S: k7 X0 u: W8 ~
2.新增- 原2 L- d' Z E* ~% T& L) P; S& I
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
: ]4 a5 Q. x& w4 R( C - $lastId = $resultOne->getInsertedId();: ?6 B" O$ t( N1 ]
- $resultMany = $collention->insertMany($array, $options);//多
' k' y' t6 \, X4 F# Q) k- q - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原& U- M( B- q/ F! m! z3 m6 Y
- $collention->update($condition, [+ ^2 ]; I ?/ a J. f
- '$set' => $values. H; E$ B& a, p& I
- ,[
: {( i, [' h; D" u& ~ - 'multiple' => true//多条,单条false% G# S) R8 h( d7 c4 R" ]* A/ P0 I
- ]);
复制代码- 新: T$ i& D* ]6 T% F3 c7 t, B- k" N5 x
- $collection->updateOne(
2 x9 o# W3 W/ h- F7 C* c - ['state' => 'ny'],
* x- P8 k0 L s% s8 x - ['$set' => ['country' => 'us']]
0 K1 S i0 ~# s3 w/ w1 R D& V; C6 r - );
! ]' R& p, Z$ @8 e - $updateResult = $collection->updateMany(
( T7 V" B; ]' M5 E/ | j8 C - ['state' => 'ny'],
# ~* e# ]/ w$ \. e$ U% y6 ] - ['$set' => ['country' => 'us']]3 p2 i: U. O6 H5 `# z
- );; A& \& {* V4 P: A
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
4 P9 Z% z6 z$ K" O* Y% v
- $cursor = $collection->find($condition, [
. _( h! b. x4 G - 'name' => true//指定字段8 @1 z% R8 v" ^7 s' T6 b# b
- ]);2 z2 T, F' N% i3 N/ ~, N; e
- $cursor->skip(5);- ?2 R: Q9 s8 D! C. D: T
- $cursor->limit(5);
6 R* _% @1 F- L1 P1 @- b2 ` - $cursor->sort([7 ~9 Y- o0 P. g' w) j
- 'time' => -1/ ^6 v) I( c' P0 e1 Q6 z
- ]);
复制代码- $cursor = $collection->find($condition, [8 w! ]; _+ P ^0 `
- 'skip' => 5,, ^) N Q7 ]1 L+ a9 s
- 'limit' => 5,
3 n, l4 H/ `0 V9 t4 y) i2 d) H1 ` - 'sort' => [
1 k0 j1 X; u( o4 A h - 'time' => -1& A2 W2 u( e' d" A
- ],//排序
% R7 L7 l. _7 r& O) }+ N- I - 'projection' => [, r5 }2 J$ _3 W0 ~! @6 P
- 'name' => 1//指定字段
% K1 q( N3 l2 x) A5 n0 S - ]
8 o" D1 y! @ _2 @* c6 J - ]);
复制代码 5.删除- 原% Y* J# U4 N5 ?* z; Y8 _! l
- $collention->remove($condition, [" p0 C3 w% q( Q3 }7 R" k/ T
- 'justOne' => false//删单条! b3 L' i6 S2 e2 ?7 U
- ]);5 q7 K3 R* o8 p! d
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);- x9 H2 |. u/ |. ~, v0 A9 J$ d9 w
- $collention->deleteMany($condition, $options);+ ~; Y1 P: n1 D3 @0 c, g9 |
5 u+ O: e, z* e( [& I0 J$ n8 O- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
" G$ v, Z7 [6 J$ i - '_id' => $tableName//我在自增表中用其它的表名作主键! g- j) n% b3 N/ b
- ], [
7 f. u' X9 `3 m2 V2 ?9 ` - '$inc' => ['id' => 1]//自增
: w: ]- L4 S9 ~, ^+ n4 s% B - ], [6 l7 F. ?5 O8 U+ @" |. _2 X
- '_id' => 08 A, M, Z3 P3 l% Z5 @
- ], [$ ^' B8 S- I! z' n V( w' P
- 'new' => 1//返回修改后的结果,默认是修改前的
2 w* x/ a( G& V% T, w7 { - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([" a/ E5 h6 r. u& s
- '_id' => $tableName
0 |# r1 L5 w% r9 @' M( }' e3 |9 U# e - ], [
! z" b, j1 o! N7 S& R9 b - '$inc' => ['id' => 1]+ a( y# G/ V0 P) \- k% Z" O5 { z
- ], [
0 J, s" c I3 g! A1 c* P/ U - 'projection' => ['id' => 1],
$ C) E" X3 A7 V$ v+ k+ M - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
/ ^% t/ X( c/ g+ a; H/ H/ B& I - ]);
复制代码 , K" } Y ?0 W& K, [1 s, t h$ t
& N( {- f+ z3 W |