|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
7 C. q A, \, s# o6 m. }) w5 s) o
G1 B' B( l- _- use MongoDB\Driver\Manager;
" z/ W3 W6 E4 U! q+ T: j3 L" s - use MongoDB\Driver\BulkWrite;8 p0 J% p, C+ W G
- use MongoDB\Driver\WriteConcern;* P+ t2 ~# K- k, I' ^' ~
- use MongoDB\Driver\Query;
# u9 y' m2 W. ]9 W8 F - use MongoDB\Driver\Command;" z: n9 _( ~* G
5 @% P6 o% G5 j# r- S" v7 M) O c+ v- class MongoDb {0 P9 L! E# \9 {. |+ k2 v( G5 Q
- 7 a% s$ t9 `: @/ v9 s5 X6 i4 ?2 U* }
- protected $mongodb;" B, s" @6 g5 y( l3 h
- protected $database;
/ g) R& v3 W- g% y+ K: x% [- y; } - protected $collection;
( u% ]" d6 T' r( ]! ~* ^ - protected $bulk;0 k( {8 J+ ^: c2 ^7 l3 O4 a
- protected $writeConcern;
. r L+ s# }7 i - protected $defaultConfig: H6 o* d5 i& ~) p$ d" a( N
- = [9 H. M9 ~4 S; S. S
- 'hostname' => 'localhost',1 [/ r( H1 H3 I0 o, d, b2 T" ~
- 'port' => '27017',% f4 _. _8 _( b# o; A
- 'username' => '',; E2 E" T1 \7 r2 k$ q
- 'password' => '',* G+ n9 m& l+ R2 b& ]
- 'database' => 'test'7 x! D: d: O% H- ?: E
- ];1 T1 |# i8 i, f8 Z9 d+ o& c
- R9 C" P$ h) |( _. d$ u l, c
- public function __construct($config) {
; j7 u( i4 H6 Z0 @- @( y - $config = array_merge($this->defaultConfig, $config);+ o7 m/ G! f, W% J; i- P' L
- $mongoServer = "mongodb://";
/ V- [/ a' Z. V8 e ~, z! W4 c - if ($config['username']) {$ Y1 P8 _6 {6 @, |6 P3 c# I7 x$ B
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';* N, l9 u( E( r/ ^4 O
- }
2 R' Y1 V7 L+ p$ E6 m* o+ W - $mongoServer .= $config['hostname'];
5 v! P+ b: E) P/ Q1 n - if ($config['port']) {
; ^, B. V% j( W - $mongoServer .= ':' . $config['port'];
7 `* J5 j+ v8 x' L' n/ V - }! j& e; }. {2 H2 {9 p0 [
- $mongoServer .= '/' . $config['database'];
" P: [. Y9 V" }7 l; h
2 Z3 `4 R# K8 D: S: ?/ X- $this->mongodb = new Manager($mongoServer);
" a! _0 y0 \! a* |3 O - $this->database = $config['database'];
) j6 T/ }3 g- s2 Q1 e Q - $this->collection = $config['collection'];
1 z. l3 O1 T) ]; g. F8 ^ - $this->bulk = new BulkWrite();+ e! n" p0 T3 o. S: c3 X- F
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
, e* R; @8 D0 e d) V" w - }
& i8 m* [7 r, x. r# D
, m, F& f/ N4 F9 [+ ?- public function query($where = [], $option = []) {
& F. r; o; t# N' K( U - $query = new Query($where, $option);8 S$ U( [% H9 ^2 Z5 y
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);4 v5 f2 s6 D; g; D; |+ q5 h$ f
- 2 y. y! v+ K# O% Z% h( Y1 Z2 N
- return json_encode($result);2 i1 e Y1 f. R E8 f5 d$ r% S
- }1 |( j# Q3 I& Y- o! ]& m1 v
- ; Z: _+ r4 ^: V
- public function count($where = []) {
' G6 h% ~% {6 E- E6 V - $command = new Command(['count' => $this->collection, 'query' => $where]);. ?, C+ i0 k* Y4 V) w0 C2 p
- $result = $this->mongodb->executeCommand($this->database, $command);
9 O) ^0 ]3 K4 A! z - $res = $result->toArray();
1 V( P- c0 X5 ?1 y+ h - $count = 0;
. b' T9 o, P( m: Q! r - if ($res) {
7 G6 Y3 P/ b/ ^5 l. C. {7 ~ - $count = $res[0]->n;+ y$ Q( e/ ?% k
- }
0 t' G8 L) ~" E7 K. `/ V; |
1 V" F8 e+ w* x+ Q! i/ V! t! _! S- return $count;
# r1 g" ~: R3 q' o2 F; t - }
; f+ O- A B5 ?& u0 j9 |$ [
% R& V* f! Y8 B- public function update($where = [], $update = [], $upsert = false) {! _" [9 Z7 c5 N6 Z7 [6 ~+ M# `
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]); E4 J: S7 K9 N* }2 C
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);, A: D) w7 s; B. E5 J
- 2 d2 ]& L1 R% i2 m
- return $result->getModifiedCount(); M7 H9 {1 o- E+ k. p: k
- }. o2 F/ R" ?- l9 [! z0 x9 n& A' d
8 k' L2 e2 t$ g* Y, h4 ^- public function insert($data = []) {: _* s4 Z9 A: E1 H N, G+ [
- $this->bulk->insert($data);5 b. `2 N6 a0 ]) {* ^% j! _# D9 G
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);5 P9 {8 I0 g6 C
. o. u; L) G$ q4 W* z; h- return $result->getInsertedCount();4 U- {4 a3 y* T* o4 o; C
- }
G% t! Q. I! d5 J0 U* g# n% ? - ) |) a$ Q+ U) p$ ~, k5 C9 o3 ~
- public function delete($where = [], $limit = 1) {9 ~& ?" p( h/ k. {# G4 w w
- $this->bulk->delete($where, ['limit' => $limit]);5 L+ h# q, X; V/ F0 d
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);6 r( Z! @- N; X" X
/ ]5 J& ~% ?* l6 W ?0 s- return $result->getDeletedCount();) i* A0 {0 @ u/ J
- }
( O1 w$ ?' R$ U0 F1 i# G - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原! {; `& e* ^: P5 ]/ Z, k" l9 }
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单8 X0 {1 Y4 q6 z9 P4 f" B I
- $lastId = $resultOne->getInsertedId();: c# ~7 T7 t ?" t. S
- $resultMany = $collention->insertMany($array, $options);//多3 j' c4 `4 x, s4 E7 H7 b
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [0 C0 q- m! c" ?: P9 r" Q
- '$set' => $values
- h3 ]& ~. d g- W - ,[6 N: l7 n# P c; E
- 'multiple' => true//多条,单条false
8 @" J6 Z7 f. p$ k7 p, G& ]* G. s - ]);
复制代码- $collection->updateOne(
O. f% \. V& |+ b0 ~7 n% h - ['state' => 'ny'],
' ?7 r/ u2 _" o; n0 {# ~( B - ['$set' => ['country' => 'us']]6 w# R2 c9 c4 s+ K& N/ {: J3 M
- );1 v5 C; {5 m) ?8 u( k7 O( y
- $updateResult = $collection->updateMany(9 W ?! |6 W6 |! z3 i
- ['state' => 'ny'],
$ C% F- q9 J( V: V3 O1 B! J& U ? - ['$set' => ['country' => 'us']]# s' @6 F4 U! F. ?2 \ Z* f, T
- );
$ v/ Y0 W2 h, S {# U - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
( Q8 F4 H# Z$ R) r6 ^ - 'name' => true//指定字段' s- e' T& w6 B
- ]);
& ~! n. @6 b4 f - $cursor->skip(5);" O- i, a7 ]& P" [
- $cursor->limit(5);% t8 Z1 t3 g$ G' ?
- $cursor->sort([! e: r" E* z+ J5 X6 I
- 'time' => -12 a: W. a" J7 |9 l0 L
- ]);
复制代码- $cursor = $collection->find($condition, [, D9 O+ q; v# Q0 M7 |4 j' F, A
- 'skip' => 5,8 t, f. T. ?; N$ p
- 'limit' => 5,5 _ ?" Y7 l% z1 c1 j0 J; q
- 'sort' => [
" ~# d1 ~, `) z/ } - 'time' => -1
0 k9 b+ h; A2 k) E9 H# _( T - ],//排序4 E" W1 r$ K% n
- 'projection' => [
8 ?5 _ v; A6 c$ c4 z5 G7 Z* ] - 'name' => 1//指定字段) V% _2 S- @2 A% w3 v" x5 L
- ]
X" s4 o3 ]5 ?+ ` - ]);
复制代码 5.删除- 原' v3 F& R4 s& f/ g p+ a, W
- $collention->remove($condition, [. K5 v- r+ E2 z/ r( A8 o- s" M
- 'justOne' => false//删单条
- N' f! M. A& ^; Q - ]);
+ e: M) `7 @4 V& ^ - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
8 O1 W6 O: N# C! I8 Q& L - $collention->deleteMany($condition, $options);
; h% x$ P; y* h
1 @4 ?- @; ^& j \. F6 q- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
6 [, i8 L L5 C3 [- X - '_id' => $tableName//我在自增表中用其它的表名作主键
% x z7 d% K1 j0 t/ Z8 \( y7 u - ], [/ i4 L1 J" T1 R8 C+ `9 \
- '$inc' => ['id' => 1]//自增
) a# _5 Q4 n4 r6 @0 B. T - ], [
4 F# ~1 l/ ]& q - '_id' => 0
$ H* P# o0 _- b, p: U9 P. r9 E5 v- i - ], [
$ y& {7 L. q$ Q3 |. B+ e t- k6 s - 'new' => 1//返回修改后的结果,默认是修改前的- F/ K8 V& t# F' V
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([$ j2 Q4 v6 L2 W- z1 }
- '_id' => $tableName
" r0 w3 j- D% X- Y) n6 Z - ], [
/ z @5 S0 ^1 D' y% Y - '$inc' => ['id' => 1]4 w4 ]$ @3 C A6 b
- ], [- G- j2 G% T" U
- 'projection' => ['id' => 1],& Y$ N! U% N7 U' o% H, t( ^1 s
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
% d9 @% i6 d* F8 g2 c( y8 {1 a5 u - ]);
复制代码 2 c6 h" H: I$ [8 _
; R" ]0 x9 k; j$ S0 X9 r& M
|