|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
" _% g, s9 a8 q, r/ H - ( n: l h7 e/ E$ s, @+ V8 K+ C
- use MongoDB\Driver\Manager;: c5 G; I- C, Y
- use MongoDB\Driver\BulkWrite;
# v X0 l0 i# f# [$ i3 ` - use MongoDB\Driver\WriteConcern;
- f2 g' T z# P2 p - use MongoDB\Driver\Query;
& [8 S4 N6 X7 E - use MongoDB\Driver\Command;0 C. t1 z1 E6 v, e& o' H8 _
- : N0 }4 M* M; \, q
- class MongoDb {
: r; L0 o2 D; H O8 B% ]. M - % I2 U P L! \/ Y3 Z! n
- protected $mongodb;
/ \, E6 |& T8 L# c5 M: Y8 j. A - protected $database;3 u! |) I, k, F' c9 U5 _
- protected $collection;3 P1 C$ U" p, J, z4 L$ Y
- protected $bulk;1 b0 t. G7 b& C" j+ i/ X; T
- protected $writeConcern;& Y" W0 z( l/ W/ w2 m
- protected $defaultConfig8 d7 ~3 y6 k" F3 E+ m: @
- = [
* ~- s% V# W3 A - 'hostname' => 'localhost',7 m( v( x" r. t6 d: E& q1 A( Z
- 'port' => '27017',
8 ]& @; \0 d: N/ s - 'username' => '',. j5 I1 H) h4 t9 N7 [" q
- 'password' => '',! `5 N' Q h+ @# c
- 'database' => 'test'* V, _4 |9 Z; [$ m# W6 H+ p1 J+ N
- ];. @8 K- Y# G( |1 l1 x9 N
- % K5 H5 O$ W1 C: W$ a' i$ o
- public function __construct($config) {
J* ]0 j# i9 y' C5 _ - $config = array_merge($this->defaultConfig, $config);
& m3 \) {& S- C2 }* B - $mongoServer = "mongodb://";' Z1 e# \! r% H" m; w
- if ($config['username']) {
* h% o$ V$ R, y) O8 K - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
$ R, }5 S# i# w% N - }
0 P. }& i$ I! a# M4 ] - $mongoServer .= $config['hostname'];
% `# _" W, n2 P - if ($config['port']) {
/ b; F/ u' C$ A* y O, r7 \0 |( [ - $mongoServer .= ':' . $config['port'];& C7 V7 \* I' e) R. }& V
- }" E; I; w O) f u5 [/ N) |) p: s
- $mongoServer .= '/' . $config['database'];
$ {) r4 U, w# u- x& ^ - # ]8 a: x! y: \: x) o
- $this->mongodb = new Manager($mongoServer);
' i7 ]& v. F' Y' l - $this->database = $config['database'];
- A. [9 i2 |# Z) o8 i; R' T0 ?" l - $this->collection = $config['collection'];
7 l C2 r1 h4 q4 ] - $this->bulk = new BulkWrite();
7 t$ X9 s P: L4 s$ m; i3 D5 i - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
! R9 t& V ~' s, u' E - }) w6 P( W; Z* U' N4 z' P* D
& D ~6 r$ \" u+ k1 n- public function query($where = [], $option = []) {& k6 z' t! ^5 q/ K3 F
- $query = new Query($where, $option);# a1 ^' u; V1 g- ~5 y% f- X
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
- ] I I1 q8 r7 I, V) v
$ b, q) B; V/ d1 f) k* o$ J8 q1 z- return json_encode($result);- t5 M7 }/ d* p6 Y
- }/ m8 }5 K; C) k$ A9 ?3 _6 f
- 7 S3 B J2 Q% D
- public function count($where = []) {8 r$ C- n7 O- w$ Y1 x
- $command = new Command(['count' => $this->collection, 'query' => $where]);
6 d& A& I8 n( ~1 B9 I0 Z - $result = $this->mongodb->executeCommand($this->database, $command);$ m! y3 a$ V! e% ] P& k" V- h
- $res = $result->toArray();! u6 S/ [/ q" X2 N* d% T9 L; n! H# x
- $count = 0;# f- {) d- a7 R+ O8 G+ d- w
- if ($res) {/ p4 L( C) d# c
- $count = $res[0]->n;6 r& q% z/ ^3 ]7 [
- }
/ n2 {# o0 t ]! B$ X
: s8 n) r' b* w# j( h8 X Q/ A5 m- return $count;5 A% x: m8 V% D1 B% L
- }0 {# i6 w: e2 _' d! i
- 6 k. N- r) f* R$ K
- public function update($where = [], $update = [], $upsert = false) {
- u1 N" b( e# n8 @ X - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);7 G4 Y8 k" I# l6 [0 c) D& s( C
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
% v, H" V5 X* t - # e! j. S6 h5 X' }- Y* Y- W4 U6 h$ q
- return $result->getModifiedCount();
% U. E3 ~8 U! S: X; d) O8 B0 V - }
, p6 z: ~- @* `1 k A" Z/ {2 p - 4 [3 h3 g: S7 j6 K% j
- public function insert($data = []) {: P Y% m6 I* i& t( `0 f6 m
- $this->bulk->insert($data);5 P9 e) ^5 `. N5 d: j+ c1 {' J' p6 T
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);3 d* B& ^& J N
- 4 a( |/ h* J) m H/ K, h
- return $result->getInsertedCount();0 u. P. S2 f1 z: \, E
- }/ ~% ]2 s& r# m5 _
P8 F; v% Z r! h5 u, Y) k" p: X- public function delete($where = [], $limit = 1) {
5 N" L; G6 Y! `# r) i/ _/ R* Z - $this->bulk->delete($where, ['limit' => $limit]);& @3 m) c, p8 F; v( U, z: B; t6 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);: _" b6 {1 v. W
- 7 U- [9 x' h2 a+ G+ E) z
- return $result->getDeletedCount();, E2 s) z- w- r- l( t8 G
- }) d* d& D# R# h$ C2 _ t9 X1 o) m
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新4 I1 i; O3 H- R' [' f) A' c$ `
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
" r% _/ U2 m1 m7 M - $lastId = $resultOne->getInsertedId();
( W2 |. `. Y0 j" h" g. m3 G: S - $resultMany = $collention->insertMany($array, $options);//多8 N j1 O2 @" X, K
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
8 M7 d- v7 @5 Z ~5 a, M
- $collention->update($condition, [
( Y" L' ]! Y8 G) _- S' w$ c* \1 p7 K0 i - '$set' => $values" ?+ ?' }/ f; a/ f0 m$ [4 ~
- ,[# N0 F1 P# g) n/ v
- 'multiple' => true//多条,单条false
) Y4 W+ L4 N( ~7 N* M, ] - ]);
复制代码- 新
" c" }, L' R) c; s4 ]% s
- $collection->updateOne(4 s9 A6 ^( j6 H" g R
- ['state' => 'ny'],
$ g; Z/ N, m% `2 l. h/ b - ['$set' => ['country' => 'us']]
$ }7 G4 i$ ], H7 c T - );
6 G" ~+ i% V0 C) [6 f - $updateResult = $collection->updateMany(2 F" r& _9 z) e
- ['state' => 'ny'],
$ j/ P4 p/ u8 x$ v - ['$set' => ['country' => 'us']]
7 e1 N2 S8 ?6 F4 R - );& z& f! S4 e+ b# C9 `
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
/ D: y# X+ C4 w+ u - 'name' => true//指定字段6 w: p. _0 [. Q% a2 _( H8 e9 W: t( g
- ]);
1 c0 ^/ Z; `6 v- w: ]( W" p - $cursor->skip(5);& f" A& N, e ~8 U# C9 }
- $cursor->limit(5);
1 ]" N5 d, P5 s. A# u9 R - $cursor->sort([* U1 p( D2 X4 V% E! n( s
- 'time' => -1
9 C4 k- W) Q4 r7 d1 O6 S - ]);
复制代码- 新
L& r8 x! X. I% P) [* e- m
- $cursor = $collection->find($condition, [
- a; s( l y2 r" Y5 ]- `$ _& K; M - 'skip' => 5,
7 }. e1 y8 @9 T - 'limit' => 5,
- i. Q1 M- G3 z" F! F - 'sort' => [
' ^7 |0 Q5 w+ p3 h) @. D& z - 'time' => -1
! _0 q4 W5 F6 M* L" } - ],//排序; m7 a6 p9 Q2 E, W, T) h& Y. P [
- 'projection' => [
3 ]. D6 Q5 K3 b4 W$ r' n - 'name' => 1//指定字段
* d! Q8 K* D! W6 M - ]
7 q7 B/ i) t5 }. c - ]);
复制代码 5.删除- $collention->remove($condition, [
% _- Y' g$ I5 I - 'justOne' => false//删单条
6 }0 h3 F- g1 M p; p+ M1 ~6 r2 `3 q( G - ]);
; L: D. x$ g# `: m& h - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);7 d9 x7 ?# c" P- T. @
- $collention->deleteMany($condition, $options);
4 p: j, Y2 W, q# p( U& |
8 }% T2 y% J" j- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
! z$ M, I! f) g* s - '_id' => $tableName//我在自增表中用其它的表名作主键+ r- w% D0 f* b9 X) o8 _, u
- ], [& p: g. t3 o& `# P$ X0 J
- '$inc' => ['id' => 1]//自增4 t3 P4 v- X. r: v3 b/ V4 e& n
- ], [6 D* E) u% ^# ?) _& K& ^
- '_id' => 0- i3 y, q+ |+ l; ?
- ], [1 O8 l/ g. i- ~+ r1 y
- 'new' => 1//返回修改后的结果,默认是修改前的( y: K# W( V$ |$ B
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([: j3 y8 a& V2 T, h
- '_id' => $tableName
K- e" K- f1 y& C - ], [" _4 x! r1 C1 i4 n! c) _, L
- '$inc' => ['id' => 1]
/ R( w5 ]4 X8 N( ~ - ], [- w; ^1 G7 H% L5 T# F+ X
- 'projection' => ['id' => 1],! J7 O6 t* C% A7 u* R
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER0 X* S& O6 l0 e: ]; m
- ]);
复制代码
, `: k# ^+ [; @( ~4 H" l; f2 z# j" @1 F2 |" T1 f+ _
|