使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php5 `( J+ F! h# b. U. D! v( p
4 W6 m2 Q! }( Y- use MongoDB\Driver\Manager;4 u, k8 j0 w8 I/ F
- use MongoDB\Driver\BulkWrite;
$ L* \. t J, X; Q- N8 G- Z. D# _* m - use MongoDB\Driver\WriteConcern;
: C6 o6 ^% M/ R7 f2 l/ n+ n% W - use MongoDB\Driver\Query;
9 u1 J O s9 O; j - use MongoDB\Driver\Command;
I) K4 J2 V* `# ]$ Q4 [ - * o2 E; M8 A- v( v; ?
- class MongoDb {
. K+ {1 Z2 R0 B$ N - # i' p8 w9 {) I2 g
- protected $mongodb;; u6 Y( r. I% S9 v' k+ a% E/ H( S4 ^$ V
- protected $database;& y% M* Q2 g, I- ~; c. \
- protected $collection;
7 c. I4 o0 a9 E0 W - protected $bulk;
0 h; O# W2 m9 z: O0 R5 n( ^ - protected $writeConcern;
! K) _$ z0 Z! \! e* Q& ?$ ^ - protected $defaultConfig3 U6 D/ A$ Y/ M$ I8 J
- = [
/ X4 u' I9 S0 ]# I - 'hostname' => 'localhost',: E x) I/ Y; X8 |
- 'port' => '27017',2 u) C/ s& ~& z; v6 e) E! i
- 'username' => '',- s) L2 W) m6 C+ h) a5 l8 n
- 'password' => '',& f7 L2 m' ?# Z3 H
- 'database' => 'test'4 r/ G, K' L* V* k( q) b; _
- ];" Q( |. q8 y0 \; b2 H2 ^. T; P# v
8 L, i' g- q4 H: t1 A. [& U& o- public function __construct($config) {
5 L' U! a% @3 f8 y% o. D, Z) x1 V3 b - $config = array_merge($this->defaultConfig, $config);4 K2 f6 m, O, O. T* j
- $mongoServer = "mongodb://";7 c+ [. Z! G% I0 o' c* j
- if ($config['username']) {
6 ?+ j# G: B9 {+ B$ R - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
# ?. S o* _9 H! Z0 l! @6 M - }
- ~/ _; O' l0 f+ s5 U - $mongoServer .= $config['hostname'];
) E2 \4 v0 y) I+ N9 i - if ($config['port']) {9 \' M! q/ i" v, I
- $mongoServer .= ':' . $config['port'];
4 Y' y5 w" v: L* f* ]$ m& r - }: D' n1 z$ [" j
- $mongoServer .= '/' . $config['database'];$ P$ Y3 V* Q7 ^( r- ~& A
* r+ o8 A+ m9 u; F+ {4 k- $this->mongodb = new Manager($mongoServer);
/ ~! ?* f# i5 N7 N, ]. k5 ^ - $this->database = $config['database'];# V3 B3 ~' Y/ t# |( r. k$ _% ?) B
- $this->collection = $config['collection'];
$ R: [1 ^9 ^* g4 ]1 u& h - $this->bulk = new BulkWrite();: b* `' h% |+ R% Q) r
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);7 ~" f# Y/ t/ {6 B4 r
- }2 Y7 S: M8 p: r v3 s5 Z4 C
7 J1 L2 E% f3 C( s0 e1 m( q. I- public function query($where = [], $option = []) {
6 l$ e2 P7 @% e, f - $query = new Query($where, $option);
6 k7 `, `( r4 \ - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
5 Z; d0 m- }: x$ E4 y3 q, G - 9 w& E' N! r$ r* ^
- return json_encode($result);, P) ~: i% K' g
- }* h# J) Q9 n7 f. N
3 q: T# {5 Z3 |8 Q! j% Z w# ^3 m- public function count($where = []) {' x1 s6 X' Z/ j- F
- $command = new Command(['count' => $this->collection, 'query' => $where]);; p, q; @( q$ h. E6 }
- $result = $this->mongodb->executeCommand($this->database, $command);
c' r0 v2 B/ t% }9 v - $res = $result->toArray();
" b) z/ E2 U3 I% u3 M - $count = 0;
* e, @/ c( M# r" H6 `0 \/ u - if ($res) {" v$ G' P: b' ]; F2 K3 g# v
- $count = $res[0]->n;
. _( Y2 Q' C5 t$ w$ \! y - }; W9 |) m) G( z
3 a: w7 S8 K, n0 _) G- return $count;% k- r$ J; Z6 v! f" w9 S& y, s1 \
- }
5 b) z- ?$ d0 e9 v* I5 t- S) u$ P
: [! d7 k: ~2 i- public function update($where = [], $update = [], $upsert = false) {
) {- H- v/ Z" ^& g$ |! S - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);4 a2 {% I+ Q* m3 [9 h
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);4 B2 U8 J0 B: W
; W4 k! s+ O( G" b2 Y& [- return $result->getModifiedCount();
. [% T7 q/ I- Z4 Y - }- \5 o, R6 u3 q* B% Y" J$ a
% X& I( D* Q- ], Y- public function insert($data = []) {
1 Q& A1 g3 m, V - $this->bulk->insert($data);/ V$ R9 S9 M$ w' F
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);0 V$ _0 ]9 j9 D9 k8 O4 p k
- 1 m4 ]- p, ~5 s) ^4 X Y6 X
- return $result->getInsertedCount();: ^7 u3 \6 r9 p8 p: W3 p
- }
& d" T- j, q3 k. y, ?* r- G. m
3 G! P3 Z+ M! d0 l- public function delete($where = [], $limit = 1) {9 P: j# D/ d8 G0 Y4 E9 n( ?
- $this->bulk->delete($where, ['limit' => $limit]);
* v& B! r: b8 R, @, u - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);5 i) X/ ^# V, Q/ i" z0 G& j% W
$ }' @% B! m3 i% @1 M- return $result->getDeletedCount();
! }0 ^ ^1 Y+ A$ S - }) `2 w4 V* U$ y
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原6 j& h) I: j* A; ~# p. ?
- $collention->insert($array, $options);
复制代码- 新
8 }" c$ a2 I+ s) S% _) `+ D8 V; V
- $resultOne = $collention->insertOne($array, $options);//单# K6 B7 J& j% X7 h/ K9 M" [
- $lastId = $resultOne->getInsertedId();
/ F9 m# Y2 ^' G* W( | - $resultMany = $collention->insertMany($array, $options);//多
! E4 y/ H/ t- ^# G9 u1 | - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
) v: _+ M v G, c. H2 {. O+ j - '$set' => $values r$ P! L/ p9 \; T
- ,[3 U( i* X" M7 I% Q: i- ~ r! a2 E
- 'multiple' => true//多条,单条false
# G) G* q0 B/ i8 U9 i7 Z - ]);
复制代码- $collection->updateOne(
% d X- |' N$ o ~* H2 e - ['state' => 'ny'],# i, y- L6 d) H7 x1 c& T
- ['$set' => ['country' => 'us']]$ V/ M; H4 s9 B# l0 l5 ~ e- x
- );1 N2 [4 y" a+ S$ m. C* A- ~5 x
- $updateResult = $collection->updateMany(
: }6 P* y7 k3 w$ Q - ['state' => 'ny'],
$ J5 }6 ]& ~2 ]7 C: j5 i$ b: Z) f - ['$set' => ['country' => 'us']]. |. S& l" O5 G% T2 o6 i) c" V
- );
4 D4 z/ B! C. r+ T% l3 Y' e+ i7 T - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原( [1 @$ C* F( `) A; S1 E( i5 t6 ]
- $cursor = $collection->find($condition, [- c) b" k) T8 I3 a
- 'name' => true//指定字段& A. R) L- l- N/ d/ H
- ]);- g# J, |' z& ~( ?' ]
- $cursor->skip(5);
- P& a! p6 ?) K7 l8 c4 A' L - $cursor->limit(5);. T* g9 N0 J7 ~) R2 p% k
- $cursor->sort([
! e% G0 j0 N9 q- K; c - 'time' => -1, ?( M9 S4 d4 v; N
- ]);
复制代码- $cursor = $collection->find($condition, [
8 _$ G4 t: Q% L+ g - 'skip' => 5,, W; Q, A( V) W, S1 J. K- T
- 'limit' => 5,6 C$ u! o+ M0 U6 C0 Z% @. P. }
- 'sort' => [* T2 r! o4 v$ w6 s+ j
- 'time' => -1: I" t4 B5 v8 m6 d5 ]
- ],//排序
" C9 ?/ S- T( A# `3 c. ~ - 'projection' => [
9 W- @9 D9 ?* k6 M X: }! D4 G* s - 'name' => 1//指定字段0 {! W+ n; S6 ]% \9 A& p
- ]& I8 C8 ^/ _, F/ K
- ]);
复制代码 5.删除- 原
" p- q) Y, F# M$ B; J1 c6 [1 @
- $collention->remove($condition, [9 Y+ J! Y: v; H; s& S; d
- 'justOne' => false//删单条+ d5 Y! ]; r1 ^4 L: c& Y+ J; {
- ]);% o% J7 {( y6 S4 h% m. R
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
3 o4 w% x1 p& T6 L0 f - $collention->deleteMany($condition, $options);
: p' ~" J# G' X, O( [2 I - / U: F h1 y6 g3 c$ M' c$ b$ P G
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
" i; y3 T' U- Q! ]/ z0 b8 Y - '_id' => $tableName//我在自增表中用其它的表名作主键
6 q) N y" I2 |) L6 O6 Y% J' n - ], [
3 ~9 _ p4 e' H& @/ R: y - '$inc' => ['id' => 1]//自增. ]/ }0 V* y3 M( q% x- C& x: J" ]; P7 M
- ], [' z7 U [" m/ O! B2 _: j* Z
- '_id' => 0
8 @. _; M) |) N* F; ^ t9 r0 k& I5 q8 N - ], [
" C6 l, L1 d! F) J( E7 ]( X' j* J5 s - 'new' => 1//返回修改后的结果,默认是修改前的
8 F' P, I8 G: ^ y0 Z - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
8 W, [9 g% { }% r- \6 Y4 Z4 @ - '_id' => $tableName
0 X n3 C! Y# l7 j6 X - ], [
2 T4 L) n" P8 ^' r5 W' v - '$inc' => ['id' => 1]
: _" y! J$ @' x - ], [8 x3 J+ D; B! e% p, W) _
- 'projection' => ['id' => 1],
% G, v8 Z0 V; k. u! S - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER4 r1 a4 p7 T0 E* G& ^
- ]);
复制代码 5 m, S3 U6 s# ]3 t6 M
; a' ]/ z# K" J2 t# f
|