|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php2 H: D) l' {4 _
- % x. x! F9 {; x+ B$ S) \0 h
- use MongoDB\Driver\Manager;
1 R; i+ e# H+ ?* N' e, N& y3 E - use MongoDB\Driver\BulkWrite;9 v3 H; W4 W; X6 l* a8 y$ \
- use MongoDB\Driver\WriteConcern;/ H0 a* ]0 S7 a$ b, S
- use MongoDB\Driver\Query; _; ~. Y5 Q' s& E7 M% ?/ O4 p
- use MongoDB\Driver\Command;
+ U' {. |/ R' z: p- P
: R# {( w% ~: V6 p0 s- class MongoDb {
: U7 g2 z4 o1 E" n- r - ; K6 \6 e: j* r; {
- protected $mongodb;9 p/ i( U0 L4 ]; \# n3 b; b( K
- protected $database;" t& r5 b9 ~+ X+ Y0 H6 G
- protected $collection;
3 Q7 \) z( e; C2 a! t& P& R0 j - protected $bulk;- j' X5 _' _8 r! Q/ p
- protected $writeConcern;
& c9 {4 K8 P8 ~! Q1 `, u$ f; ~1 s - protected $defaultConfig
4 z- [! Y/ d0 F- { - = [
# J; D8 `3 \3 q0 w - 'hostname' => 'localhost',% N& R# M$ e+ j
- 'port' => '27017',3 S- i+ o7 \6 I" [% G
- 'username' => '',( c* ?/ S+ n' _. j2 {' r5 E& c
- 'password' => '',
# r! e! }9 ^1 t7 u+ g0 F - 'database' => 'test'
/ T5 t- U0 ^7 T& g/ k - ];& ?7 O! }! o" ~6 i/ G U3 L' r, K
) S( e0 f0 y0 [6 F4 r- public function __construct($config) {6 d; I1 L' ]$ z7 I
- $config = array_merge($this->defaultConfig, $config);
+ j- O6 b* b2 n# [" t - $mongoServer = "mongodb://";% ^5 {( H5 X2 a- I- j7 y0 R9 b
- if ($config['username']) {( |/ ]- T2 G O
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';8 L7 w9 k w4 \" w r8 k1 d
- }3 I( g8 s* {8 b" c
- $mongoServer .= $config['hostname'];
) X, c* F: z y* W2 L+ c# N. ~% D - if ($config['port']) {
6 g- I6 v2 H2 h- a' ^4 P! d4 z q - $mongoServer .= ':' . $config['port'];8 e: ~4 \7 ~& o7 Q8 u+ t! [4 j
- }& R# `9 X2 ^) a2 r ~, E
- $mongoServer .= '/' . $config['database'];" ]$ r, |* x3 i/ q1 x
5 G2 l7 S2 T7 ]( C1 v/ T- $this->mongodb = new Manager($mongoServer);) f! _. b5 @' p' P3 R. y1 A# F, R/ v
- $this->database = $config['database'];
" d) E- q8 _2 X, Q i6 x - $this->collection = $config['collection'];
7 u$ B5 F7 {! T% [" Z9 e( y! L# f% _ - $this->bulk = new BulkWrite();
, E$ y: E0 W0 k& O' q5 i - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);1 L& t* n0 H- R! g7 W5 K0 D- ?
- }
9 H0 J+ x0 N! U- j8 N! H2 `. { - # P% {: M1 A( Q
- public function query($where = [], $option = []) {6 T1 l. D: t9 H8 `$ Q# v2 s b. F
- $query = new Query($where, $option);7 R. @& L5 Z2 l) }$ Q
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
# i" O5 \8 W" }# P, P - " D( @/ Y% n9 }- }( o' E
- return json_encode($result);
' {( \; V2 r, c- T; m. I - }3 c) a; d' {9 [1 @. H
- / C2 _* j5 b7 W; A4 d" v6 k
- public function count($where = []) {
) w$ @0 z/ k! C' m) d0 t - $command = new Command(['count' => $this->collection, 'query' => $where]);
3 K, l' [; @* G2 c! } - $result = $this->mongodb->executeCommand($this->database, $command);
" e0 m4 J3 \6 y7 E {* o - $res = $result->toArray();
% I8 j% s) @' B2 k, `0 x6 `. Q - $count = 0;
# W" y! X+ D; o - if ($res) {- P% z) H Q! `6 A
- $count = $res[0]->n;
, U1 ]/ E+ s/ i8 e - }8 E* l; O$ q4 \
- * l. Q6 ^ F: P
- return $count;( y2 H* J2 x5 n+ ^" x, T2 p. L
- }
3 y7 E( ]% X2 P* U1 `
6 Y4 b( n( p6 C: `. @( W- [- public function update($where = [], $update = [], $upsert = false) {
& j) F9 J+ _" n# | - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);. u- j- f1 `3 d" n6 g
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
7 z8 L* ~6 A' [9 u
% s% Q& B1 `* K# g! A0 g, n& |, T1 Z- return $result->getModifiedCount();# v) t" n4 t. G+ n n
- }
5 X( X$ b0 v) o2 Z. x8 |# ] - 0 Z9 ]$ m9 ~8 v$ `
- public function insert($data = []) {
- D+ e+ A" I) u - $this->bulk->insert($data);
4 w- ?- m" f7 X( t - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( ?8 a. I7 ]) ^# S, A0 [ - 0 |8 k3 S9 {% s7 E/ y' X
- return $result->getInsertedCount();
1 Y$ K! k& A2 F v+ z% E - }3 D6 W0 P/ h/ c# F
- ) U7 a& A; d5 F+ Q, _ `7 M9 p" ~
- public function delete($where = [], $limit = 1) {" t# J) F2 N* k6 `
- $this->bulk->delete($where, ['limit' => $limit]);
8 }( G# }6 I: S+ ?; {* ~ - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
3 B5 \8 m( N8 B' F( O$ N" }# ~. N - / V5 h7 W3 N9 h; X
- return $result->getDeletedCount();) G% G' |' {3 ?9 |
- }
% g. e& F6 R- V- H& C - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
8 J* v6 s2 B2 i7 w+ ^8 M% i( Q 2.新增- 原8 K" \* G: U( x7 e5 s9 p4 O3 M; w/ B
- $collention->insert($array, $options);
复制代码- 新
# j8 ?: t! c# h: @! _* g+ _1 R
- $resultOne = $collention->insertOne($array, $options);//单
6 N! s! ]( u" ?' O - $lastId = $resultOne->getInsertedId();, U& _* @. ]6 N3 w2 F4 A
- $resultMany = $collention->insertMany($array, $options);//多
( _+ p3 T( s4 P; L" J - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原- v. d( h/ I+ S" }# d: t+ r# K
- $collention->update($condition, [
' Z) a; e8 A' S& V0 {8 N2 B - '$set' => $values5 D- o1 e/ m) |. S" s
- ,[, u* b4 ^4 V! v" W
- 'multiple' => true//多条,单条false
$ h0 ]( V& E# W6 A f - ]);
复制代码- $collection->updateOne(3 U. {4 m! U& I$ z
- ['state' => 'ny'],
' Q" M7 i' I: O7 k* r" E9 t - ['$set' => ['country' => 'us']]7 ~9 x: U6 }6 M# |* o* b- z
- );5 w) ]' B- S8 x+ g
- $updateResult = $collection->updateMany(; U) u# ^; n: O' m: k! z4 T
- ['state' => 'ny'],* R5 D$ z7 T2 v, u2 W3 f
- ['$set' => ['country' => 'us']]& M! I1 B$ a/ m0 P$ r7 M
- );
2 s1 V5 h$ o1 C7 p* } - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原6 _- B- I" a _2 i4 ~8 s- o
- $cursor = $collection->find($condition, [
, i) t6 v* \& S2 s - 'name' => true//指定字段. L" X( G5 ]8 n1 G0 u
- ]);
" f) I8 z: _; K - $cursor->skip(5);
) J/ w$ V K+ N3 Y+ u - $cursor->limit(5);
( j& |! M9 }/ P) V$ M$ b% g - $cursor->sort([
6 R i0 B9 o8 i$ K- Y - 'time' => -1. K" ]/ u* u- R& J
- ]);
复制代码- 新# H0 a: _( ^& q7 `' l2 M: U
- $cursor = $collection->find($condition, [- l, m6 f) F: w% H0 a
- 'skip' => 5,
( n) C" ]: E% o, w7 O - 'limit' => 5,
7 b [, \9 e" c2 Y' e- U5 b! e+ A3 U - 'sort' => [
: D3 ~2 O$ \# f* E - 'time' => -1" k; O$ A r% a+ g
- ],//排序
9 ]+ U) {( e5 B# x2 X - 'projection' => [
0 i O ?* l0 h6 S - 'name' => 1//指定字段' Z% _2 Q' ]/ D6 s% @1 u, ^9 F
- ]+ W* @' @3 e4 V# w: X. g0 z
- ]);
复制代码 5.删除- 原
0 |- q4 w, _+ x+ O+ d1 E1 @$ W
- $collention->remove($condition, [, [. c1 H2 j( Q# U
- 'justOne' => false//删单条
0 T2 w* C1 I' c - ]);
5 S) K C( P7 x3 q6 W - $collention->remove([]);//删所有
复制代码- 新1 y; H! E3 n$ D4 D" T+ _+ Z1 [
- $result = $collention->deleteOne($condition, $options);8 O% D- j; C8 h7 ]: \! w
- $collention->deleteMany($condition, $options);0 R% w G2 k; V5 w2 s8 ?$ o
6 Z( L( m$ p2 L( b9 {- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
7 I$ Q9 C9 x( ^6 u' X: ^! e; o - '_id' => $tableName//我在自增表中用其它的表名作主键
2 o8 d' k6 v" W) c7 n, M# p - ], [5 f! r% G8 V" ]: k: |" g
- '$inc' => ['id' => 1]//自增
0 P7 L% k. v3 X0 _. x6 ~5 h - ], [' ?. T3 }2 ]; N' j/ q j; e
- '_id' => 00 E. V8 A( A& O% Z! S
- ], [% ~8 x9 Z, }$ C+ \. \# c, q
- 'new' => 1//返回修改后的结果,默认是修改前的% x/ N8 N$ [7 |% m3 ^- J7 _
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([3 P7 K, g' Y E0 Z5 p
- '_id' => $tableName* k7 A& y" F4 w& }' Z
- ], [
- ]6 @5 Z% x3 {( U - '$inc' => ['id' => 1]7 @: a: ^) K* q/ M+ ~7 P# t
- ], [8 w0 ~0 M* s' Z2 C* }
- 'projection' => ['id' => 1],0 s6 S" h9 i2 L, K
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
" b6 x8 r2 K1 n, M2 b - ]);
复制代码 0 ^. M; p. k2 m p8 B" t4 Q5 |1 `
' A9 c# m) Z( e0 L; r# W5 P
|