使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
9 C+ R E! _! O0 h
. u7 o# N. s4 z9 n3 _+ W- use MongoDB\Driver\Manager;% W8 U) N5 }) c7 \
- use MongoDB\Driver\BulkWrite;. c% Y ~* v& z4 e. M' G, [- V
- use MongoDB\Driver\WriteConcern;
+ F: W& W c, r - use MongoDB\Driver\Query;
( g+ w- T' y @& ~, W5 O - use MongoDB\Driver\Command;& Y' h* X; f4 T( i; _# R! Y
$ d! \5 M0 G* q; n5 D- class MongoDb {/ E* v! A6 y8 r5 O0 c" E
* _8 b* u8 f2 {- _! w$ C( T- protected $mongodb;3 H% ^) M! g, w7 F
- protected $database;
! ^ y5 v0 m2 E8 ?4 S9 f0 r - protected $collection;
( _1 i7 }- W3 V! q - protected $bulk;
6 i! I$ g) c" G8 }7 [1 E - protected $writeConcern;
2 `2 G4 k# A* U% b - protected $defaultConfig
3 x% `8 H5 J1 w, a - = [
+ B) N- B( O3 q7 [ - 'hostname' => 'localhost',
: a* H& x5 ?* X: x - 'port' => '27017',+ C( y$ ?4 H, w* t- R* ~5 z
- 'username' => '',1 F2 T$ U! y7 N. H) N4 L
- 'password' => '',
2 J, U, p v( O% U0 b - 'database' => 'test'
" R1 P6 n. c! L4 L0 q5 Q* K - ];
0 _, E6 F; L( ?; L - ; x! {7 @9 Y- _1 n2 c
- public function __construct($config) {
; s* n- G+ T; p. p5 E8 m! [# M% }8 M - $config = array_merge($this->defaultConfig, $config);
% l; c6 M' t1 r% J8 z - $mongoServer = "mongodb://";
2 Q# b9 M6 M) g* U - if ($config['username']) {
5 J# _2 t$ i5 y C - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
( D6 P7 P( a6 t: T - }
" }6 u. ]# [* N& S8 p - $mongoServer .= $config['hostname'];
: _* O4 W3 ]+ | - if ($config['port']) {3 r1 m3 S0 z8 n# o
- $mongoServer .= ':' . $config['port'];
" C2 h* d; |. {( d- H) B# m - }
) a! r) W, s5 b$ C - $mongoServer .= '/' . $config['database'];
+ }* ^: `) {" d
% f( i+ A2 \- I' R% K- $this->mongodb = new Manager($mongoServer);' u: |7 t9 K& k* ~) c( a, I
- $this->database = $config['database'];
! T4 K' Q6 T8 L V; p, e - $this->collection = $config['collection'];1 O& h6 m! N; O$ @7 S
- $this->bulk = new BulkWrite();- O$ F/ F8 |! x) I4 r7 b( t( I6 B
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
( I7 S$ s6 |, N7 v8 l - }
1 t8 E) j/ D% i
, p& @* q% K( J& T" F/ O- public function query($where = [], $option = []) {0 O J# b& I4 K$ `7 r A. n3 i( p" e; N
- $query = new Query($where, $option);5 _5 r7 c- b. f
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
7 ~3 N4 T4 i3 D9 \# I; P - 8 G- R( Y' y" V; G
- return json_encode($result);$ a* s7 |( f+ T9 u: G! V# g* S
- }) s! o8 H- i1 L8 T# u( |
( y+ B+ `. Q6 m. B% Q: I0 P4 u- public function count($where = []) {
+ P5 {* R& I; }' Z; i2 F, p# A# f - $command = new Command(['count' => $this->collection, 'query' => $where]);
- T$ m2 V5 w5 l+ { L - $result = $this->mongodb->executeCommand($this->database, $command);! {7 ~5 c C5 v( b9 ^1 G
- $res = $result->toArray();
' {: |. y1 @, ?/ ]( F8 c6 o# ` - $count = 0;
$ d# @# V8 _* U3 t# [ - if ($res) {$ J1 y n: ~. y' |4 v( h
- $count = $res[0]->n;* w- A0 q7 C* G; G# ~
- }8 C+ f* ^; j: B* B4 N4 \
- , X" h3 v$ c5 {2 O: i
- return $count;# G' [ n+ S: Q2 k
- }
0 I3 ]- ~4 ?8 q- C* n - 0 Q- W2 A5 b( O G
- public function update($where = [], $update = [], $upsert = false) {
& ]: b7 n; h4 T* N& l6 g( M - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
S. M/ r$ |0 u" @% c - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern); P3 {& _! w- u$ t3 D [& J& D" I1 Q
- ' A% o' A8 N% ~6 r$ @7 Z+ K: ^
- return $result->getModifiedCount();
3 l* d$ O, U3 d/ _" L9 C/ ?( P - }# x3 |/ n" b8 |2 T2 u% G/ Q
# |/ w1 h# }! x5 R, q; G4 b6 k- public function insert($data = []) {/ R+ }# l6 I ~+ c; W* C
- $this->bulk->insert($data);
/ ]5 u' t8 w5 L& e" a, A) ? - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
9 ?' p0 J; i: P0 h6 F - ! s+ P8 T) G2 w
- return $result->getInsertedCount();
- N' i7 ]8 P) ~% A5 O8 a - }' z3 K. ]7 g4 U J
( b( y; Z) ?2 l S" T. L* I- public function delete($where = [], $limit = 1) {
0 B* p2 m# S: F9 ]: g - $this->bulk->delete($where, ['limit' => $limit]);
+ `4 ~$ `' P9 x - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. x: }9 |9 r$ M5 p) D! ^ - ]# E# ]; C: [
- return $result->getDeletedCount();
) M2 k) H/ I5 L - }& }1 a9 I9 m, K5 R4 M- @# _+ ~
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
% n& ^' r# b+ @% D& K* a; o 2.新增- 原
* S7 s$ A7 F' B+ c/ e D+ j: o4 x
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单! l- }! }" g+ X" b3 x
- $lastId = $resultOne->getInsertedId();
+ U5 c! J) \) F, q - $resultMany = $collention->insertMany($array, $options);//多
0 j1 k& t3 z4 [" V5 R) w" c: f - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [: z% @) @5 ^! A. G
- '$set' => $values
9 g. [- r. ]: A# e& ` - ,[
7 P2 G3 \9 b1 h7 h1 u - 'multiple' => true//多条,单条false6 W' Y, n3 Y: A: S3 S; e* k: B
- ]);
复制代码- 新- V6 [% P/ q# ^* a6 A7 k) Z/ k
- $collection->updateOne(
5 I3 {, g. o5 }0 V2 a- v - ['state' => 'ny'],
1 {7 n# F+ T+ i$ P( n- h& C) { n - ['$set' => ['country' => 'us']]' a' ?1 s/ L, B! I8 p; F @' D
- );
& c# d1 w! S, E8 `3 x/ |7 ^ - $updateResult = $collection->updateMany(
' ?! [3 r& k/ P J - ['state' => 'ny']," f; {, f' W' r7 g9 o* ?
- ['$set' => ['country' => 'us']]
- A: g, {. [$ s$ y - );
+ p, R6 ] _ l1 p3 W - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
+ X4 o: f1 h7 ?* c0 `8 `9 n1 H
- $cursor = $collection->find($condition, [8 z( J* X& V! W& x
- 'name' => true//指定字段) [4 p' e1 x; ^) v7 q' M) S
- ]);. q# v+ |8 X- E/ r" n: t
- $cursor->skip(5);" x3 B+ [1 T/ {. k* P1 ? \
- $cursor->limit(5);/ N4 D7 C/ P! l3 \ a! L
- $cursor->sort([
2 O7 t; `& A4 |8 M+ Q3 n - 'time' => -11 ]$ M3 j8 J$ E5 D9 d8 v: }
- ]);
复制代码- 新
) j& ?) Y$ `7 w G1 B& ]/ o
- $cursor = $collection->find($condition, [
1 f" f) i, L% f! C" v" e. N6 w - 'skip' => 5,
' \% d+ D9 L: A% z0 ]* u: D - 'limit' => 5,
2 l& d2 O t" D3 ]9 C/ r - 'sort' => [# p" l V5 S0 p
- 'time' => -1
; [! u4 P4 ]) `/ q4 H - ],//排序
( P6 m3 e1 R$ }: i5 Q5 s0 o! d6 A - 'projection' => [
& H* W. a! k. ^& s7 _ - 'name' => 1//指定字段7 m( j- r) Z9 a5 U2 d3 v9 i
- ]5 |; `: g$ A. d$ ?8 H9 e- X: x) _9 X
- ]);
复制代码 5.删除- 原
1 D. r; g- Z6 @. P! \' T$ K
- $collention->remove($condition, [2 }* o. a# K. f
- 'justOne' => false//删单条0 `1 K4 O# X' y9 [' W
- ]);! n% {8 x, U% G' i
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
% L$ r( C8 ]1 x( J' \' w8 z - $collention->deleteMany($condition, $options);
# m; Z7 {+ t: K" ^! B0 n1 M5 y - 8 C) D7 m' d j1 c# e! W
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([- |$ R+ ?1 P4 {
- '_id' => $tableName//我在自增表中用其它的表名作主键1 f# b8 n$ g6 Y# F9 |
- ], [3 y2 v6 F6 a1 q- w( J( H
- '$inc' => ['id' => 1]//自增
; b" G9 r! J) A# ? Z0 h - ], [
* B# {& s. f3 o8 Q - '_id' => 0
4 p6 J* M) f% Q" j# X - ], [. q* J- n& E7 N$ B0 j! j1 b6 o
- 'new' => 1//返回修改后的结果,默认是修改前的2 t; [: Z9 {7 w: l' h9 A- [+ O
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
! W- \. p9 M6 E- V( C' w! d - '_id' => $tableName) ?/ O, X8 e' g8 L
- ], [
$ o9 M8 q/ X8 e" J% w0 ^ - '$inc' => ['id' => 1]: E5 ?+ V; p, {; B4 o4 E
- ], [+ P* ^( j& L z0 [7 \0 {
- 'projection' => ['id' => 1],+ c$ m% Y( u0 O- X
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER+ H \3 u0 Y( Y P7 @- y4 ^1 P
- ]);
复制代码
( I+ u% k6 y9 G! E3 K
8 ~" Z5 S1 `: z3 {; C' U |