使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php! }5 T0 K8 i5 a- r4 ~+ E7 F4 A) c
- ) Q% B: k3 K' `; J
- use MongoDB\Driver\Manager;0 X) J! v5 e7 w* Y* m$ l
- use MongoDB\Driver\BulkWrite;5 r$ j0 m. k! }6 O$ x; p( o" t
- use MongoDB\Driver\WriteConcern;
) Y: ]1 i! @! i7 o- }0 V ? - use MongoDB\Driver\Query;
( F6 n) F. T1 U, p# r - use MongoDB\Driver\Command;4 _% G- T4 h; F0 {% Q+ C
, C' g6 X8 f# E, t- class MongoDb {
; M+ A8 Z6 D: i; ]9 z - ! h6 c3 J1 O; R( j# P; u* p) Y
- protected $mongodb;
+ {6 s1 v5 P; p( `4 a+ | - protected $database;0 y9 W3 w. b' R0 j
- protected $collection;6 q! `1 M9 r% n+ `+ _; q/ D
- protected $bulk;' {. P% T; W; P. J" H* }
- protected $writeConcern;
, c& p6 f3 @( j/ T M - protected $defaultConfig
# y! H8 f8 |/ i' ~- U% H" {& Q/ u - = [' x8 [5 c" C- \
- 'hostname' => 'localhost',4 ]0 p' P) J3 ^% @$ l7 H) x* _' i- S
- 'port' => '27017',$ C, @* k' Z) a
- 'username' => '',9 j5 ?. G9 n' z
- 'password' => '',4 J# W7 c( L! N9 r# C
- 'database' => 'test'0 A) f1 i! u) M: o+ Q* L8 x6 Z
- ];0 D* a5 j' j! o6 i! K2 u
4 L, |% Q z) W! h/ P) Q- public function __construct($config) {/ N; p- D/ O- A6 T% e
- $config = array_merge($this->defaultConfig, $config);" L& m n( U+ v# R% _5 T
- $mongoServer = "mongodb://";
% x! _) k1 p1 {0 e - if ($config['username']) {
' v' k9 y# j! q7 R - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
6 i# X! r; A4 f9 g - }8 R9 ]7 E* b8 R% h7 {# P/ K0 y7 b
- $mongoServer .= $config['hostname'];
- h' _6 C/ p# n2 Y& r - if ($config['port']) {
! s$ ]$ `# s- e& W9 V- Z/ r6 N1 o7 M - $mongoServer .= ':' . $config['port'];
7 y) a$ V; `2 n - }8 l2 @& v9 [$ }* R+ l0 D
- $mongoServer .= '/' . $config['database'];
' h# s, q1 m/ Q. c( q$ E
- F5 L9 U) C! N, J2 _1 m7 @- $this->mongodb = new Manager($mongoServer);
* B( m/ V/ h7 s1 X: c - $this->database = $config['database']; \1 q2 C, v. O1 i" k
- $this->collection = $config['collection'];1 Y& n5 _( V$ ?! b1 o! p) X6 w- W9 c
- $this->bulk = new BulkWrite();
, y8 }# Z9 {' D5 } Z1 t5 N3 s - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);5 o) @3 n: I. ~" ]
- }
1 Y: o: \2 A/ h/ {7 w - 4 g* V9 O& I( m# z u( ?! y+ S
- public function query($where = [], $option = []) {. _4 e# y6 N* T! _( q0 K
- $query = new Query($where, $option);
3 L8 v, K r6 o% D; h8 X" Z. P - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
- ~1 V$ T: I( q% M8 x3 Y - # G X S* g0 D$ G2 O6 g) O: I
- return json_encode($result);
1 Y8 C/ f( w% ~" x" F6 @$ o5 @ - }
( n* Q- J! j q; w - - W( G/ g( c& F
- public function count($where = []) {
& e' b4 z8 y* m' w& K$ f/ \ - $command = new Command(['count' => $this->collection, 'query' => $where]);/ B" `- Y, R% }# y; Q
- $result = $this->mongodb->executeCommand($this->database, $command);
# S; g* ~( D5 W - $res = $result->toArray();
) C t v/ ]6 N; T ^6 E - $count = 0;
: P4 a6 f( n- W+ z - if ($res) {% r% Q7 \/ O# \8 G
- $count = $res[0]->n;% J5 R$ q9 S( c$ ?' a
- }3 N" l* R, S/ F) D
4 X& l9 W& M& \1 o% B# v- return $count;
2 }+ R7 u+ O! v& O' u/ K2 }8 F - }
0 }' }% m- Q3 @, C+ Q1 u7 b; L4 t
! i6 W8 M; g$ F+ b) D7 g) I- @5 w- X- public function update($where = [], $update = [], $upsert = false) {# [& G( J' v `
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);# k( E0 B+ ?2 r& T2 v+ q
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);, b: S' s4 X! k2 S m5 {: k" e
3 b: D+ S) l; }* }" H5 z& q- return $result->getModifiedCount();; W6 b( @: j, a ^* A
- }9 l8 ?% [' o& S: h& U
- 5 s5 ~3 `6 a( i2 Q8 x$ [# e
- public function insert($data = []) {: S3 \* b0 ~4 p; U$ C* k8 h
- $this->bulk->insert($data);
8 v6 C; e0 r6 Q* M) {0 r/ p/ A# T0 Q - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 W: e; ^6 G. @7 \0 ~& z% T
- ) F8 a% c$ _1 E4 F
- return $result->getInsertedCount();
5 ]* Y6 N: t8 M - }
. B. e4 W. P+ @
# }6 `& h8 h+ A1 L2 o8 w, L- public function delete($where = [], $limit = 1) {& X& w% W8 a+ D9 K1 e
- $this->bulk->delete($where, ['limit' => $limit]);% c6 ]( ?* I9 a K% |
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);) G9 m" T6 X; T
5 b# M( Z& H: D0 ?- e. g: [; }1 d- return $result->getDeletedCount();
9 o% u, }) e0 E+ q/ } - }, L; p9 ~$ D5 T9 I3 c, e1 q- m7 J* V
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
7 N9 d: y- H1 i4 h. N# p9 g8 Q 2.新增- $collention->insert($array, $options);
复制代码- 新
3 i2 ^8 k1 R/ o% x& _' u
- $resultOne = $collention->insertOne($array, $options);//单, O; @1 |/ Q G+ `, A% O+ p
- $lastId = $resultOne->getInsertedId();3 ?' {4 B- t8 G. R0 P- U+ r
- $resultMany = $collention->insertMany($array, $options);//多
k- |0 A* O% b - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原6 f) x9 z) {% K l3 Z: X+ e) ?
- $collention->update($condition, [
1 l, z2 [6 h% z; f! }: o - '$set' => $values* Y! R6 h w8 k' \
- ,[
; B% f% d0 {0 }: I5 n: W, { - 'multiple' => true//多条,单条false `2 ]5 Z5 j7 w+ H8 t! M7 c! P/ }
- ]);
复制代码- 新* ~; Q6 v i+ C$ b/ R- I0 B) _& e
- $collection->updateOne(7 L& W L" ]( C4 f3 Z3 }$ w+ s; @2 g
- ['state' => 'ny'],
; C4 a8 ^* L0 ?: N7 J+ Z; l - ['$set' => ['country' => 'us']]1 p6 J2 }! |+ w% T0 N' P* |3 c
- );
0 s- t/ i3 S9 x) Q% y2 M) @1 l - $updateResult = $collection->updateMany(( C) b* {+ R: g8 z
- ['state' => 'ny'],
- n: S" l2 u- A- w& s - ['$set' => ['country' => 'us']]
+ u, X6 @3 n. ?1 }- h( X - );
6 K, y1 U5 @6 [ - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [$ s# Y) J2 f( {/ E' | E! b4 k
- 'name' => true//指定字段
/ K4 A% L _" y) K - ]);
8 J) K. Y7 F6 L1 [8 s' X: L1 | - $cursor->skip(5);* ~. @$ L$ ?! N2 P0 [ \+ O
- $cursor->limit(5);
( g r( q9 L5 ?! E3 i; ] - $cursor->sort([
9 D& j) m! _# S" u - 'time' => -1
( u F7 A8 M! f, l - ]);
复制代码- $cursor = $collection->find($condition, [6 q N1 e8 P" D! a9 @
- 'skip' => 5,, T3 ?- G% F$ U
- 'limit' => 5,
+ p! ^! {; M3 |& X/ N6 t - 'sort' => [* ~% {! i, g: I5 H3 x3 X3 Y; I
- 'time' => -1
4 F+ r' K& L Z5 |- |/ U7 z) r - ],//排序
# C. o8 W; w" f7 [ - 'projection' => [
0 `& d |& X8 F% u - 'name' => 1//指定字段, `7 ?3 i& J# C4 U. L: g" Y4 Y9 \. B
- ]
1 I: M1 L3 l. F4 w7 S) | - ]);
复制代码 5.删除- 原
$ d \* ]! e( F9 i, u: u+ [ U- J
- $collention->remove($condition, [
- _: R$ a7 n. L' f% j$ C - 'justOne' => false//删单条( T; Q4 ^0 \0 H" ]5 P- D
- ]);5 o6 h: p8 X- y+ A
- $collention->remove([]);//删所有
复制代码- 新
# f6 D% R: i! u9 Z. S7 T* ?
- $result = $collention->deleteOne($condition, $options);( @1 Q* X5 p. o) Z7 t9 h" {
- $collention->deleteMany($condition, $options);7 h' s0 Y7 I# [2 u C6 r
f" O( o4 C5 V, o- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
& Y0 b% U. @7 x! t - '_id' => $tableName//我在自增表中用其它的表名作主键
8 d% N+ O) ^- u, P - ], [/ Z- D+ E0 [/ ^% `6 T X
- '$inc' => ['id' => 1]//自增# l% C. ?- C$ w: K5 T3 s/ M
- ], [
1 h& f) b H5 ^9 a+ Y5 s - '_id' => 0
3 J) M7 H+ f9 e5 I) G: |( z - ], [9 i' |5 d8 z ~% ]! h
- 'new' => 1//返回修改后的结果,默认是修改前的: v' y( b2 z z( @( V+ y
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([" o9 c- E; L) ]0 S9 n5 Z0 |' }
- '_id' => $tableName6 k& K \4 M, v4 E% c }3 d
- ], [7 x+ B" f3 @: ^ @* c4 X0 X3 h
- '$inc' => ['id' => 1] k) L8 P/ K5 D2 g: Q1 w, G
- ], [
- [5 c: y x' T: A/ l3 ?3 h - 'projection' => ['id' => 1],. l7 g" E) Y$ s: A* s% v$ D
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
8 D" X9 q4 G7 D' m8 h8 n - ]);
复制代码
* N9 y5 S% g- t; ^( s0 w) Z1 K) t' A( }. ^( o
|