|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php( B7 i6 W5 y6 F! W" ?+ O2 L
3 v4 @; z8 _) ]" H( ?! H- use MongoDB\Driver\Manager;* [/ B5 C" ]! e$ P
- use MongoDB\Driver\BulkWrite;9 u3 E* F5 R4 g; F) G- V
- use MongoDB\Driver\WriteConcern;
. G1 r' q% z) d8 i) K- K - use MongoDB\Driver\Query;! F% q+ f; b0 f2 F2 p3 |# |3 @
- use MongoDB\Driver\Command;: ^5 L; X7 h* { M) c2 v: f
, i% h+ j0 { t; e( l# }8 [- p5 i- class MongoDb {
; _7 ~% u8 B) G0 a+ g9 j( X! W' H3 w
. K+ x/ E, | M- protected $mongodb;8 I' {, w4 A) v0 }: S. ~
- protected $database;
1 U7 _6 i3 A8 E+ S) C$ J# W, J* \ - protected $collection;4 K Q$ Q1 |0 v% J6 W/ Z
- protected $bulk;7 Y% D3 F' Z' @) g" Y( o
- protected $writeConcern;
0 u4 J9 f* g t, x5 C8 N& k) T: Z - protected $defaultConfig
2 W, d5 j, i8 e8 g - = [
/ f. X8 w' d5 z* v0 M0 I7 K, b - 'hostname' => 'localhost',: d# ~! r2 J) q- f# w$ b5 n
- 'port' => '27017',+ b: t% @/ g5 y) W' l/ X
- 'username' => '',2 `% }% N: `! b0 U
- 'password' => '',1 ^, I1 ?, u' l8 r' M @0 n Q3 [! j) L; F
- 'database' => 'test'7 n6 E1 \9 q: s2 U1 P
- ];
1 R- o; [1 b& A4 f" m
* @8 I8 s' Y( }1 x1 f6 e- public function __construct($config) {5 ^8 I% r* x1 a0 o: J" q% @
- $config = array_merge($this->defaultConfig, $config);8 n; t! D" P5 F2 }9 ^7 U; H N+ {
- $mongoServer = "mongodb://";
$ n2 `. s/ T8 A. U. C - if ($config['username']) {1 e n j3 q& l/ M0 [3 o
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';5 }. t% A% ]9 F2 G3 Y8 ?) x* l$ b
- }" @: f2 S* I2 l, W
- $mongoServer .= $config['hostname'];
* B1 _ Z6 q% @( y, ~* c - if ($config['port']) {3 k+ d( M, M5 u: F: A# d
- $mongoServer .= ':' . $config['port'];
* s# [ I% d; @) j7 ~ - }
+ y. ^7 ^2 j! H; H; `# M& B; ` - $mongoServer .= '/' . $config['database'];9 ]- F1 n9 [2 U, u8 Q, v
; Z) Y! v$ F1 x+ ]- n$ G- $this->mongodb = new Manager($mongoServer);
& W4 W- ^* J; ^) L' b, `% N' k - $this->database = $config['database'];
+ i( s, V0 y# I9 u" m8 w - $this->collection = $config['collection'];3 c! w$ O0 G: J, a' g
- $this->bulk = new BulkWrite();
0 h& Y" z) y+ E2 h; c - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
0 |8 k; X6 o+ J4 C - }# K& p' o2 z3 \4 f0 M* }7 @" @
- 2 w0 \9 `3 w) B' a$ I# R! y
- public function query($where = [], $option = []) {
+ A$ }# F" G5 L( c - $query = new Query($where, $option); O$ j" m, H9 i( X. F( r9 L4 F
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
. Q' o b1 \( `6 @
% w1 t/ Q7 U: w: O4 g J. N- return json_encode($result);, Z$ j" @8 l) Y- G9 V5 M( _
- }
" R6 p' [& ~9 |0 U# Y$ I1 i - 3 y! W6 O+ C$ L. p# | c& F
- public function count($where = []) {
1 ?9 [/ c- c: y( r1 c; i - $command = new Command(['count' => $this->collection, 'query' => $where]);
) x9 F* R' }! e# v - $result = $this->mongodb->executeCommand($this->database, $command);
0 o8 a- y3 U) |& |+ K/ b - $res = $result->toArray();* x; v% g+ W. a
- $count = 0;
! y& o0 J. @4 | G* ~6 T2 B+ C - if ($res) {
2 w" U4 H% ]. u2 L% c! f6 F/ ~6 P - $count = $res[0]->n;# W2 @* T7 O# v3 f2 O# y
- }
+ g) N. ^# {) d0 P4 W - / h- r9 \$ ]+ Q# Q/ I" F
- return $count;# \- Q9 s: ?5 a
- }
- o' Q" _, v- n8 Z - 2 `$ W8 {; s; G0 u0 N
- public function update($where = [], $update = [], $upsert = false) {4 H! r: \& F( E& }+ i8 K/ z/ _
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
* `7 f, G* c7 H; U - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
; |$ G3 m8 I4 Y2 a9 S/ j& T+ i; C7 o - 2 F) k: w, ?7 G1 [- f8 J
- return $result->getModifiedCount();
8 V$ E# |3 n( I6 b0 l - }
$ t9 p$ Q/ ~$ ~, o3 } ^$ h2 m - ! @' j% g- L4 s. z
- public function insert($data = []) {" O1 y$ d9 i1 L5 l+ G1 G5 P3 j
- $this->bulk->insert($data);
( B6 |" S% D3 p5 ?: u6 @/ L. { - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 ^6 y" `! O5 m - ) z8 L- d' Z P3 i" ~& V5 _
- return $result->getInsertedCount();! H+ ~, D3 ?& Y( e& \' M, v
- }2 g+ e$ c* k( x" R: D
: A ]& \3 G9 u/ E6 c- public function delete($where = [], $limit = 1) {
7 ]4 [. K0 Z' Z- {, x - $this->bulk->delete($where, ['limit' => $limit]);6 |, A5 q3 N6 Z) L7 ?- E/ {
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern); i' L5 T. z3 Y! W
- : g5 H& W1 n1 w! C5 R: ^
- return $result->getDeletedCount();& r p! G9 O8 I' M @
- }+ ?5 `/ y; Z. s
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原
4 G4 P: a" n" \3 M' s1 x
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单 V( r% E9 N Y
- $lastId = $resultOne->getInsertedId();0 j5 {9 j+ f! T2 d. E5 }% e
- $resultMany = $collention->insertMany($array, $options);//多5 Y4 o- c6 v8 R
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
6 T. u6 N7 j1 b$ j5 @, f3 y
- $collention->update($condition, [
! b' F9 }8 A0 ~9 Q+ O/ B - '$set' => $values
- H9 E- A/ f. P5 \/ N - ,[9 S# V' C2 v( b, |' J* q# l
- 'multiple' => true//多条,单条false' G: @' w& u6 u0 u. r
- ]);
复制代码- $collection->updateOne(' l0 R' |; u$ f9 d0 k. b
- ['state' => 'ny'],
& R7 l6 |9 `8 A# g% m - ['$set' => ['country' => 'us']]% S+ `+ ?/ Y# i: O9 A) ~6 `$ k
- );# i$ s& `% ?7 B+ i
- $updateResult = $collection->updateMany(0 ?# m4 H5 T# u9 ~( M
- ['state' => 'ny'],
3 r7 g) L* }. x3 C c, G5 l" i) H - ['$set' => ['country' => 'us']]
5 _% J* S8 f% c4 v' P - );
# t- {& t( ^; r' M' y4 K - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [3 U: b9 l- k" p
- 'name' => true//指定字段
6 D. Y0 F5 F) {0 r - ]);! K9 m9 c/ k- ]. S9 ~
- $cursor->skip(5);
. I, Q0 t5 e+ c - $cursor->limit(5);! n# y0 M8 Y8 P" [- D
- $cursor->sort([1 @5 k" k. ?+ p
- 'time' => -1: N# X; r3 C4 Z* w/ |# i, C5 X" U
- ]);
复制代码- 新
, B0 ^) d. U% n6 a& J' W7 D. Q( L
- $cursor = $collection->find($condition, [0 j1 J7 i3 h9 e$ u" D
- 'skip' => 5,
3 A- @5 m4 S l8 Q( J7 t - 'limit' => 5,8 M2 E. x1 ~& J9 N3 A/ K! R: X7 ]
- 'sort' => [- Y/ D! n+ f! ^ X& }
- 'time' => -1+ B; Y8 z% n9 u
- ],//排序, Q0 i1 m0 \9 K5 s/ ]: a
- 'projection' => [# H1 E! m2 k( r" g: f
- 'name' => 1//指定字段
9 x" x: `" S! b% I - ]* L% } B8 {6 H6 r& B( n
- ]);
复制代码 5.删除- $collention->remove($condition, [6 n: Z% L% ~5 U7 o. `& j+ {3 w
- 'justOne' => false//删单条' r* O0 K# g( p; ]! T# T+ r( I- Q
- ]);2 N4 W$ T& ^" U2 ~8 U" X
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);% v- Q; R8 K" g* }' B/ T
- $collention->deleteMany($condition, $options);9 O- L8 C1 ~9 `
- 1 _$ Y$ X% I& {
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([2 A/ R0 v4 U0 U) U* i
- '_id' => $tableName//我在自增表中用其它的表名作主键6 a1 S8 [- Z' Q* ~4 u1 G. F
- ], [
( y! b# S! M# p8 ^ - '$inc' => ['id' => 1]//自增: Y( y0 C* S O
- ], [5 B) R2 i/ B& s7 [/ S
- '_id' => 01 F% w# G N3 O
- ], [+ v! B- f; P5 N) n( I5 |
- 'new' => 1//返回修改后的结果,默认是修改前的
% r2 X% d; g1 f( p - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
1 T. z) j3 s7 g6 n6 Y - '_id' => $tableName
1 \& n* _7 N& |8 D) \ - ], [3 R# }) Y" `! ?* I- _/ v I
- '$inc' => ['id' => 1]
, K [4 k' w; i7 k& l" p7 r - ], [
# K' h/ p* S- c/ @3 Q3 {# L - 'projection' => ['id' => 1],9 q, @2 _/ W0 |. V; K$ Q
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER! k% A( ? M- ?' k4 ^8 @
- ]);
复制代码 $ Q+ U, d7 ^/ |: _3 o8 m
9 w6 }! W4 ^9 }# P$ W% Q' k, @+ \ |