使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php2 I% t6 h, n! m; F% E. e9 u/ |
" P! Z( y- j1 ?" P5 R. \( _: w- use MongoDB\Driver\Manager;2 y6 z" v9 g" |. G# s2 |
- use MongoDB\Driver\BulkWrite;
" g* C2 K0 L; V& p - use MongoDB\Driver\WriteConcern;8 {, `( G8 y0 E6 R3 F+ Z/ f
- use MongoDB\Driver\Query;
- l2 z0 U: B f% t3 R - use MongoDB\Driver\Command;
I1 l4 j) a1 [# j* k+ p+ d - * \* ]. b6 @; ^
- class MongoDb {# _# y* J( ?+ R% g8 W1 X. L
- $ C6 I) h5 z5 }* @8 d7 j2 s- `
- protected $mongodb;3 `: c5 I3 T! B/ i; Z
- protected $database;
/ S: X! U2 Q" |! w- S+ | - protected $collection;
- ?7 z# ~/ _. | F7 K. M - protected $bulk;, l5 u0 g+ ?; z+ Y; G
- protected $writeConcern;) A) _( |8 \, [: ?+ K
- protected $defaultConfig1 l7 t2 y3 E5 I" ]# z; k
- = [$ V; E* {# Y1 z4 `3 |
- 'hostname' => 'localhost',
* E% k: w# O- e# @ - 'port' => '27017',
% G; a" m" M3 G- O2 f - 'username' => '',
. W9 r0 U+ D. K" v% q1 A - 'password' => '',0 ~4 F2 O6 o/ P+ X
- 'database' => 'test'
, D: H9 N& W2 l' V3 }+ E - ];
, U- A9 z! O) i
8 a: ]7 q( k5 F* {( u" _9 N- public function __construct($config) {
6 \6 Q* s" f- e# C% Y% i' N - $config = array_merge($this->defaultConfig, $config);- Q \, q/ E$ Z' v2 |* }* w. J+ _
- $mongoServer = "mongodb://";
! ^1 u; q T" m; e6 Z. m$ J1 H/ D. N - if ($config['username']) {* j# ^) d* z' P! @! |
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
8 G9 J: x" k8 K3 L; Q& D; x - }* t; }4 q9 L% m* b! K; s
- $mongoServer .= $config['hostname'];
8 [0 r- X" x) ?# O7 } - if ($config['port']) {
6 W/ I9 ?# g- u2 |# h+ p - $mongoServer .= ':' . $config['port'];2 A2 k& `2 u/ j! o( \2 e
- }
- C1 q$ ?0 H. g - $mongoServer .= '/' . $config['database'];
5 ]+ O# \8 n6 B2 t4 [6 k5 [
; O3 B; W; r8 d% z$ {- $this->mongodb = new Manager($mongoServer);
6 |/ G- t. m; O5 u8 ] - $this->database = $config['database'];" K3 m. J# t5 M! d0 }; X2 Z
- $this->collection = $config['collection'];6 |, W; z; Y$ Y0 }* [+ f; u- Y& |
- $this->bulk = new BulkWrite();$ o1 W0 O/ g) j! L
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
8 a/ g) z8 w1 `/ H- u" M - }
1 t* ?3 ` k7 ]$ M* J1 z6 ^8 [0 b
% a3 Q0 }9 K! \/ v. q: \2 U' ~- public function query($where = [], $option = []) {( w3 z* \, |: |8 `$ ^# h& j# w9 Y7 R0 p
- $query = new Query($where, $option);+ h0 ~/ G6 S: ?
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
( F! d# \8 B! p9 h4 O3 A& `; o
. Y* A3 f/ q1 F/ R& S9 a& X- return json_encode($result);
# Y ]+ b8 r3 v1 p+ _ - }" l1 p- ]7 f3 J. v% i: ~
- " g- N$ O0 U3 ]- E. i# r
- public function count($where = []) {
: n! T3 i u' e* v; I. A2 I; [ - $command = new Command(['count' => $this->collection, 'query' => $where]);2 E" Y( y; A4 Q' U9 p$ Q
- $result = $this->mongodb->executeCommand($this->database, $command);7 b# o2 ~- P% O+ |4 V( U$ H/ K
- $res = $result->toArray();
$ F$ a' N$ |3 F& o- z, W; z; \) ?# ` - $count = 0;
2 ^" x2 g0 ~3 _7 {' _$ v* T - if ($res) {
, i% \' P0 u2 v3 U* i8 C - $count = $res[0]->n; q1 J8 z" p7 Y* l1 e" {% |
- }
* p: O f {& i) ^: d( W+ I, K) n
* q- y( {' Z* a. b9 `+ y0 D2 R- return $count;
* p; v" o0 T1 Q& j - }9 l- j5 H* j1 a7 p( M
- : I( e! W e/ ^) R# _* U K
- public function update($where = [], $update = [], $upsert = false) {. d, m- r/ ^4 }! s' u* l( ~5 x
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);, X m' z/ v0 R; h+ Z- v
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);4 {' l2 P* A. R5 r
( F1 |# Q2 Y3 u! X( C* j- return $result->getModifiedCount();
% Z) F! }* r0 w3 X! Y - }
8 f3 W. s0 v- R
6 }3 p+ w0 f0 E3 F- public function insert($data = []) {
& C' v5 o e* ^1 a. X - $this->bulk->insert($data);
' Z# W- S6 r9 c1 R. @" j, D - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 b( J: w+ `! q3 G" X
- " I. ?5 b0 s0 d1 M" i
- return $result->getInsertedCount();2 I1 c( u6 Z4 ` B
- }6 Z4 M# ^8 @2 H! o, i
- m9 C. M6 b! d6 a* ]* f
- public function delete($where = [], $limit = 1) {
3 S! `4 y# ^6 J; K ? - $this->bulk->delete($where, ['limit' => $limit]);
( }9 ]9 g6 h6 Y7 s! Q - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( d& c* x- c. i! T - ~* X5 b8 L8 f1 W
- return $result->getDeletedCount();
, G8 L* w4 B2 `. q - }
" l. B. m- f! U0 E' a* h - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单. ]9 A; l0 L) Y
- $lastId = $resultOne->getInsertedId();7 E% V' k' ~! i# U) Q$ V+ v8 V
- $resultMany = $collention->insertMany($array, $options);//多
6 F* T+ |! h2 L! ~' _ - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
' t3 }( y. m: [% @, D9 n
- $collention->update($condition, [( h. @; z: A; {
- '$set' => $values
* l* {' Y9 }( P) @- n7 W - ,[
: v9 n# C' G5 ~( W) i& v - 'multiple' => true//多条,单条false
% o! v1 h& ^4 u0 [2 E - ]);
复制代码- 新" S6 X3 y/ S( B0 c, p& o
- $collection->updateOne(
* ]% K, d) V0 [$ l2 P7 H- u3 m - ['state' => 'ny'],
" o' q% E4 g8 _) k1 ?6 n( I - ['$set' => ['country' => 'us']]
% Z. j) d* m2 | I. b - );1 K/ B( \+ h% R* `& Z* O- e
- $updateResult = $collection->updateMany($ z5 E3 u/ b$ h9 q" `) z2 R! {8 R. a
- ['state' => 'ny'],' E1 ^) j' o# T8 ], l
- ['$set' => ['country' => 'us']]
/ G# T/ X% x) `7 d+ N# [) B$ m4 E - );" ]9 l' _8 a7 y+ j# I+ E7 C$ U
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
* O* g6 @% l& a0 R; W' s. j
- $cursor = $collection->find($condition, [4 K) F6 m4 X S' n$ Q a: w/ R; m: o
- 'name' => true//指定字段( R* }* | h! i$ E& u' c; Q( [
- ]);9 g9 d0 d% H. @5 c& O
- $cursor->skip(5);/ e" V. s7 @6 z% N' _
- $cursor->limit(5);
, c5 d1 f0 V7 E0 z& c. h - $cursor->sort([1 v4 M& ?* ?9 O' Z
- 'time' => -1- g# a% a C; | U$ L0 S w
- ]);
复制代码- 新
& c: M/ D& l7 b5 A$ ]$ y$ s+ f
- $cursor = $collection->find($condition, [
+ @: b+ O- N: }% `+ J$ a! ` - 'skip' => 5,
- G' U" g3 K G; i8 p - 'limit' => 5,
+ U& A. |5 f5 q) e - 'sort' => [% ^. f- K ^ `2 k4 \, Z
- 'time' => -1
/ k/ ~9 J# d! J) L$ _/ B' X - ],//排序0 x: E. c$ w w8 H9 z. y5 C4 G
- 'projection' => [
: `" B! G$ Q, q2 O, V - 'name' => 1//指定字段
6 m; M# Y5 q( g8 V - ]
( J* I( j Y& D" s& B - ]);
复制代码 5.删除- $collention->remove($condition, [6 H+ F0 e- s6 S8 @! s3 h- I; Y9 S
- 'justOne' => false//删单条6 X0 R% C8 R0 _: @1 d2 h
- ]);+ j# q( `* u. C- f, X7 s2 w B
- $collention->remove([]);//删所有
复制代码- 新
! m. r; m/ B3 R" B$ Q; Q" c
- $result = $collention->deleteOne($condition, $options);
U/ q1 x' `% N2 j - $collention->deleteMany($condition, $options);
$ Z: f; j+ q8 g2 m+ R" Z
" ~3 H2 }2 Y0 h- F5 y9 E/ Q2 J$ D- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
& m# t) T- c5 _. H, @) p - '_id' => $tableName//我在自增表中用其它的表名作主键: W: P1 {& @7 ]* }4 j
- ], [4 d1 `) h5 v, |( U/ I
- '$inc' => ['id' => 1]//自增+ A/ u0 J3 D2 Y' x8 f/ \9 j
- ], [
' i; {* D6 `. s" q$ R - '_id' => 0
$ E6 \! N' [; Y+ u - ], [& H5 b# X3 p! ?
- 'new' => 1//返回修改后的结果,默认是修改前的5 S0 K1 ~2 K2 w7 B
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
3 ^3 u* v3 }: y0 B* W - '_id' => $tableName- Y( F. \! N) C, o- c* X( i
- ], [( j+ }3 D4 C& N+ T) g
- '$inc' => ['id' => 1]
9 b2 h! |: L( \, P) j4 s3 l - ], [& B2 W/ P! Z% y5 p
- 'projection' => ['id' => 1],) s+ z! S' M) q! Y2 \5 |
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER% v+ D7 y& c' C5 }; X# e6 C
- ]);
复制代码 & y6 Y& A3 t- W% a
) I- I6 L$ K7 ]4 C8 O9 ^
|