|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php8 O: @6 g d0 B7 |1 M2 T# O
- . L& Q$ z/ P1 w+ N, Q
- use MongoDB\Driver\Manager;( T, T. _/ t7 `) T7 _9 E% ?. u5 {
- use MongoDB\Driver\BulkWrite;
- [* E. Q" s9 t' L - use MongoDB\Driver\WriteConcern;4 X9 ^- S% G; @, e/ M
- use MongoDB\Driver\Query;
) i; G! b$ _& `, w: U - use MongoDB\Driver\Command;
- z7 K# b5 W7 @2 O0 `$ G0 {
7 f1 F$ g( C! ^& G$ s! Z. q% b- class MongoDb {; i7 P# C; @0 Z; U$ U
- + F8 i0 O; O9 w- u4 g! |
- protected $mongodb;
, G0 W6 X, L6 F: A3 D - protected $database;6 @. G& c4 e6 k, p A, A9 [; U
- protected $collection;
+ N9 u5 i1 O3 [* `- J6 K - protected $bulk;5 T' O. {4 e7 g
- protected $writeConcern;
1 {' l7 [+ A ~! ?# o8 z - protected $defaultConfig
8 k. s( I3 e" ~ - = [6 v0 u1 z) p; R: M- P$ `
- 'hostname' => 'localhost',# F( b9 M6 y- f! ~& s( f. F
- 'port' => '27017',) I0 g7 ^! S& Q( ~& Q0 K) E j- ~
- 'username' => '',
0 r- f6 e6 ]! Q' C$ o* F4 Z ~6 W" o - 'password' => '',
Q" a3 n! Y/ }+ G* J$ k - 'database' => 'test'
% Y. U: Q9 t) }+ k" W5 S& U' M - ];5 I2 D, d8 A' ^/ I5 [/ I
- ! \9 t7 \! F- B* J: ~- d9 j8 e
- public function __construct($config) {# \/ Z7 H; z+ O" P$ |( S" j" F2 y6 J
- $config = array_merge($this->defaultConfig, $config);
# x. s7 s( |' Z - $mongoServer = "mongodb://";8 Q0 |9 I/ x9 ^( F1 X5 L" _3 t" H
- if ($config['username']) {
$ g5 e# ?) F8 j" | - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';( z1 U& S b7 z7 E# J2 u
- }! \' v3 z0 j6 Y6 i4 B4 |! G
- $mongoServer .= $config['hostname'];
# D _; z7 V* ^ - if ($config['port']) {
0 g1 L0 Q Q/ d3 a2 V7 V - $mongoServer .= ':' . $config['port'];
- v5 r" Z6 C/ U4 x3 D9 N$ ~ - }0 R7 P f7 v3 o, J$ t, S& y
- $mongoServer .= '/' . $config['database'];
* x9 y n, Q# }$ n( f7 x. @6 y - 2 @+ _6 u; c" ^: l
- $this->mongodb = new Manager($mongoServer);& q) o+ u: q' V9 d% |% Z1 }
- $this->database = $config['database']; Q$ o- b$ D% E, F; H$ X
- $this->collection = $config['collection'];
: W6 d* p4 o# x9 K J - $this->bulk = new BulkWrite();
2 L7 N9 r: M& G. r$ R+ K - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);! |1 o0 ?7 i, A% }0 Z+ c( J( W
- }! R1 I2 O0 I9 `6 l9 W4 h* M3 g/ z/ V
2 e7 e. L% y) }, s7 v' A" `- public function query($where = [], $option = []) {3 b" a- n" Y# d; k Y& t
- $query = new Query($where, $option);
+ n2 ^$ i) ?, |$ s9 C' q - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);2 t% i: }$ F; `( M5 O9 J
- 9 b1 P4 S2 K/ z
- return json_encode($result);
8 p. ?# Z+ d1 ^ - }6 p0 T5 m/ y: |4 F* p
5 e; I3 p( x, `; _) z. p- public function count($where = []) {
' }! n' s: v5 @" z) g/ V - $command = new Command(['count' => $this->collection, 'query' => $where]);
9 c% u/ m. T: H. C$ F# m. |" [ - $result = $this->mongodb->executeCommand($this->database, $command);! L5 p9 n1 G0 [; C! j! }3 X
- $res = $result->toArray();3 j& _8 f; F3 O, a7 f: E. n
- $count = 0;' S1 A7 D4 A* {6 s8 a) D6 |$ h0 U
- if ($res) {
4 x! o7 f; q+ _1 | P" Z$ d - $count = $res[0]->n;9 m& t% i( Q1 X3 b& O. l, o
- }' a% j, B+ p) O% z. M0 q
- : L, I+ P! q% t5 Q7 w$ F6 U+ W
- return $count;: s3 }$ X! l7 w! u! A: a+ S, p. U
- }1 ^) x5 e; o e
- ) J( X: ]" v& K4 K0 A8 N; }% E
- public function update($where = [], $update = [], $upsert = false) {3 F5 g* N3 W% t' R
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);) A, |7 V) v# K3 A: N, S
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' w4 O T" P% \# v+ R }
- 6 W' x+ q& f n2 h+ g, T) P
- return $result->getModifiedCount();
( S3 l/ Q: E6 o7 L - }
: v7 d" \5 X4 [$ Z7 h4 D" P& S# V
4 h1 z4 S* U+ ]; z- public function insert($data = []) {
8 ?8 [8 ?; l7 a h - $this->bulk->insert($data);
3 H4 c3 W- j% t6 ]* ^' j8 G - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
' w1 J# j0 L6 {! I+ Y$ U9 [
4 ^% O- P, s L/ y- return $result->getInsertedCount();
: P) N! h0 t& Y - }6 E3 W$ ~+ y4 ^! D/ ?
- 8 R8 x+ p. e# K" W# ]& M" U2 Q
- public function delete($where = [], $limit = 1) {7 h! t' ?" N6 j6 o- c
- $this->bulk->delete($where, ['limit' => $limit]);4 ?/ m$ Q" m% Q& T, T2 ~
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. ~2 p( G8 d% P8 n
- / Q, I$ S* r" G4 Z
- return $result->getDeletedCount();
3 z1 s% I7 N0 e( b7 S! J9 p - }
0 M) |. @& o( v9 F - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原1 ^" ^( p. Q2 t! Y; M4 i1 s
2.新增- 原
4 {% }$ M7 F! u/ q, e8 R7 N, ]1 G- G
- $collention->insert($array, $options);
复制代码- 新7 c0 @4 S8 |6 C& H5 G5 K* v; D ~
- $resultOne = $collention->insertOne($array, $options);//单: m0 l" U0 V% n4 p% A! r8 Q
- $lastId = $resultOne->getInsertedId();
5 N. t; I4 R" v# Y1 Y. e- C - $resultMany = $collention->insertMany($array, $options);//多) `" T" Y' T, g) o1 ]
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [1 s: `' Q# w, U$ Q: l! d) X$ Z
- '$set' => $values
: n$ i0 S- U3 [ m% r. f8 J - ,[
* h: z( y' U& k* L: R - 'multiple' => true//多条,单条false
7 |7 H( D, L+ J* H/ G' S' Q - ]);
复制代码- $collection->updateOne(
% K( p; @3 F G4 U - ['state' => 'ny'],
( O7 V( M% w, r1 }8 A- a# U - ['$set' => ['country' => 'us']], E5 A) A# q2 q8 ]
- );6 |/ D/ _6 J5 q: D, G7 f/ c
- $updateResult = $collection->updateMany(
% x2 J9 ?2 c+ L9 Y" o - ['state' => 'ny'],
* C" {/ b5 n: E* @ - ['$set' => ['country' => 'us']]4 b4 p7 }+ C* `& _4 P7 m4 H
- );
& i( }) r' c1 R3 L. R - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [/ A* C1 B; q/ X
- 'name' => true//指定字段# J6 l& L4 F) R5 n6 A0 @ f
- ]);
) i, G9 m3 s) A - $cursor->skip(5);
6 g# J+ o% F$ t W. l - $cursor->limit(5);
! F+ D+ j* W; Z! D4 J* S - $cursor->sort([' u4 O! M- N) O$ {) m1 j
- 'time' => -1
, b# t$ x5 C. b7 ^3 N! J, _4 n - ]);
复制代码- $cursor = $collection->find($condition, [" w( E6 ?$ X/ |2 y; B& p, ~
- 'skip' => 5,
& w5 F' u" S& ?: R5 H - 'limit' => 5,
, |7 `) X1 d4 C7 _' h" M. N7 N" h# ` - 'sort' => [
& z0 F. G( f: h8 |" a- e - 'time' => -1
; V( c% H: {6 |4 K) H - ],//排序$ }! |$ B, @9 p% Q* N0 z# ~
- 'projection' => [- Z4 ]8 I+ c D9 y1 V5 x
- 'name' => 1//指定字段9 w/ E# ]9 i& | W# }% l
- ]
! r. @& `# C- N3 N - ]);
复制代码 5.删除- 原2 d a) N2 x+ U+ z# Y" l" E( O, P
- $collention->remove($condition, [; s& H. |; j1 S
- 'justOne' => false//删单条
! |, v5 F6 o j* u - ]);
3 j p" N; O7 r1 R$ X* p- ]) a - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);/ ?5 O2 y3 I7 ? L' q$ ]/ A
- $collention->deleteMany($condition, $options);/ f( p% x* p m1 P7 M- e% j
- 2 Z/ q Q: p, g Y5 n1 _- O9 ]" ^
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([ `4 l% F8 w# w) t
- '_id' => $tableName//我在自增表中用其它的表名作主键8 I% |! w4 L1 C* T ^0 Y4 {
- ], [
+ w& Z6 [' N9 K0 q4 a1 L - '$inc' => ['id' => 1]//自增
% V6 p) O( J3 X6 a+ U3 P - ], [
0 [7 O8 F% t, g: i) Y - '_id' => 0
R) u: Q5 n3 _; U5 S - ], [
8 x |) x: I% y4 _* d" r - 'new' => 1//返回修改后的结果,默认是修改前的* o" G8 @; T1 E1 ?* y
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
; d! D- c' I1 S. V [ - '_id' => $tableName
, S3 y3 G5 X! J- `3 K" c( w! { - ], [
5 J: S t1 U/ y* P$ d( | t7 ^ - '$inc' => ['id' => 1]
0 _. C& U+ P/ r" E2 \ - ], [
+ V6 W8 Q9 V# ?/ N7 _ - 'projection' => ['id' => 1],# v+ \" J* R3 s/ K
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
6 y& A3 I' p) X$ E6 Y6 F - ]);
复制代码 0 R9 g; M! M% t( Q
- W1 C) q: n) U5 x
|