使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
/ E' r* h# a. G: Y. M - ! T$ M% j+ E: |$ W+ ^6 T D
- use MongoDB\Driver\Manager;
4 j9 C5 O' D- i0 _. _5 Z - use MongoDB\Driver\BulkWrite;# I9 Q4 |8 C6 f( p" x" ^! q" m
- use MongoDB\Driver\WriteConcern;+ {8 K4 P1 U% s" @/ M! C+ o1 `
- use MongoDB\Driver\Query; i2 O5 `4 j5 [6 U9 Z5 `, H
- use MongoDB\Driver\Command;4 H# Y% I. m4 `# [
- " L3 D( Q! }+ e0 Y; m9 s- V3 _
- class MongoDb {
. I h. \; H2 w5 J - 2 D3 z6 ?: t0 m F8 [ f! ]
- protected $mongodb;
2 L M7 N @6 ~1 P6 M. T - protected $database;: I6 E. F4 ~ a6 ?7 E& M3 v
- protected $collection;
4 W1 z$ \8 R9 z. H, u - protected $bulk;+ x% i) l" t) y1 J$ a
- protected $writeConcern;' B) d' Z- B( v- _: B
- protected $defaultConfig$ h2 `6 j) X8 s; G' s! H
- = [
& X+ i J) x, _ } - 'hostname' => 'localhost',
8 ?: c7 @1 ?/ O4 i3 ~ - 'port' => '27017',5 f* F( v/ J( z. L# c
- 'username' => '',
) D- G7 D6 h9 l H& }1 Q2 T( H - 'password' => '',% o/ f; |0 K0 q: X5 d( y
- 'database' => 'test'
% d- X* J& i/ v+ B1 O- Q; u - ];
! z7 f8 m% U. c5 \" _' e) x) `0 y5 L
( W& p+ ^6 `1 H. X- public function __construct($config) {+ }$ j5 d: r& M8 S' L! N! |
- $config = array_merge($this->defaultConfig, $config);' @6 k4 E O3 s6 w
- $mongoServer = "mongodb://";
4 J h% ?$ z6 S3 Y - if ($config['username']) {* J. u O2 A, w
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';+ r# l. f6 X5 O- [& m
- }4 c4 H$ O4 u E% j
- $mongoServer .= $config['hostname'];+ F- \( ^7 a0 s: c' w- h. E+ D
- if ($config['port']) {6 D5 l; B* ?/ E$ W
- $mongoServer .= ':' . $config['port'];
! ], N$ D# e8 o - }
/ q& x) `# _: ] - $mongoServer .= '/' . $config['database'];
; w- s7 x# n/ J' _% t/ i - 0 P: X) A# O, {8 N
- $this->mongodb = new Manager($mongoServer);
5 q) V' A6 ] K+ V4 L3 k4 x - $this->database = $config['database'];* l d9 J y( c) s# N: U
- $this->collection = $config['collection'];/ X; }5 m- j% P1 z
- $this->bulk = new BulkWrite();
5 S2 S7 O8 ~0 V6 }! \ - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);6 Y% `; T5 F% z: P8 s! O3 s- h
- }$ Y/ z7 |" y9 y* U
3 g$ n! n& [- t5 h: T- public function query($where = [], $option = []) {
% w- |$ G0 t4 d" }6 g - $query = new Query($where, $option);
# K `. r; P; h$ v' I - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);, c, d, j4 [1 P3 C' \0 `1 l
3 M; [6 [7 t( L; v; g& C+ L) s. l- return json_encode($result);
9 N* X; [6 H: e ^2 i3 I4 }7 k - }
6 b/ Q( X* s8 R( E( e b
2 T, [, ~/ w8 I* E- public function count($where = []) {" ~7 @( W% q! A" K9 M$ h$ v
- $command = new Command(['count' => $this->collection, 'query' => $where]);
0 c; r) t4 Z5 o* o2 p! }- ]3 I8 ~) @3 D - $result = $this->mongodb->executeCommand($this->database, $command);' f& p' B6 a7 h* t, v
- $res = $result->toArray();
# L h8 g( L, R+ x( H - $count = 0;
# z- q3 _; m* Y+ j1 A. k0 C - if ($res) {8 u; x; p8 E, |! Y: H: I
- $count = $res[0]->n;, x3 S5 F6 ~" |+ w
- }# r# z# [: X5 y
- - F8 Q9 g8 J1 Z7 \& {; ?; W
- return $count;
+ h/ ~+ \/ O( c - }4 S& T' p) u ]
, }# Q- Z; x: S7 w# `4 l- public function update($where = [], $update = [], $upsert = false) {8 x; x" k# h, K4 Q& u) ^) C8 s
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
* f; M4 o" A8 U - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);3 r( E, @% @& h* H3 M/ U
6 A" B/ |, U8 f+ f: x- return $result->getModifiedCount();
8 ^. Z7 A2 S% g& R - }
, n# T. ^6 ^7 E! l9 l
. Z" H `. Y4 r9 \) f- public function insert($data = []) {
' q6 Q3 |" @+ @8 A( I9 q - $this->bulk->insert($data);
D- |* b3 I' { - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
4 I( p8 M) h$ f - : f6 g# J" |6 Y5 x, P6 H6 x3 P+ u$ H5 V
- return $result->getInsertedCount();2 P! w& s4 f& A. |
- }
8 \- \9 j0 z" s# l* S - $ {/ L( u" C( D' ~( n! f
- public function delete($where = [], $limit = 1) {
% _& f+ [4 [' I8 t) Y/ W- e - $this->bulk->delete($where, ['limit' => $limit]);( K. P# J0 Q! M/ ` X3 B$ X
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);: q* X7 U+ O' P/ n
- 5 |* s2 k) d% y/ ~
- return $result->getDeletedCount();; v# C9 Z4 a, f& w& y2 g: d
- }' }1 }" p: g- d' f6 C {- \
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原% _- W4 [9 b3 @+ X7 @! b
2.新增- 原6 r* \& o, ]9 A h/ ~. \; k+ b
- $collention->insert($array, $options);
复制代码- 新
' B3 e, [0 r; s% C- A5 H! z
- $resultOne = $collention->insertOne($array, $options);//单+ m5 i6 f9 y( j. b$ O) T
- $lastId = $resultOne->getInsertedId();% E# R0 Q& |: C* D
- $resultMany = $collention->insertMany($array, $options);//多
- R0 X* C' Z# p" w$ Z5 z - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [( S) ^# v; p7 k% p% A
- '$set' => $values
% D/ ^' P1 X# x - ,[9 o+ T. U! b9 I- H" G4 w0 ^
- 'multiple' => true//多条,单条false$ Z4 x& K0 U$ A) {0 D3 O! E
- ]);
复制代码- $collection->updateOne(
" ?0 S# p8 }+ k+ _4 f& c. y( P - ['state' => 'ny'],
- A* `6 M+ r- B# h( w6 H - ['$set' => ['country' => 'us']]- d; l$ E& {7 W0 a4 X* P
- );! r5 B% b% g" O$ n; K2 k/ \
- $updateResult = $collection->updateMany(
2 W& E! c, N& X! a3 L - ['state' => 'ny'],
/ k+ X0 R0 @! C$ Y6 n1 A$ h - ['$set' => ['country' => 'us']]. ~/ _7 z2 w1 B
- );
, W' M- ~' X4 i$ e' Y9 F$ V1 Z - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原. c& d. w3 G* p/ n7 G9 \
- $cursor = $collection->find($condition, [
* b; Q5 s8 o" `& ^2 Z2 H3 p - 'name' => true//指定字段
2 ^. c* H# Q4 {& P - ]);# T5 o, V! O; c0 v; g
- $cursor->skip(5);
- X5 I' p0 m$ n - $cursor->limit(5);5 m* O) Y5 I* D0 d
- $cursor->sort([
$ e, J* D& c7 I4 j - 'time' => -1
0 {6 T3 }% R- I2 B. P6 ? - ]);
复制代码- 新; O. f! k$ o! [$ O1 p l0 k' e
- $cursor = $collection->find($condition, [! ~. e' |% Q, O3 L( J
- 'skip' => 5,
5 Y+ ~" A' y( L" ]4 k: D - 'limit' => 5,
2 p0 Z" h/ Q% B& \" `, S/ n - 'sort' => [
1 ^0 J- w0 m S; p - 'time' => -1 I( Z" U" ]" h: [' S9 P% Q6 U! r2 c' g" A
- ],//排序
! `$ b0 e% p3 m. q - 'projection' => [8 o) v8 f- `1 J7 E2 O" o
- 'name' => 1//指定字段
: D ~6 k4 z* a- ]# `3 h9 g - ] ?2 [9 L5 I( K, S' o1 N
- ]);
复制代码 5.删除- 原0 K/ E- B I4 k: E- r+ f% @
- $collention->remove($condition, [
' W i( w: k* u1 B T( P& J - 'justOne' => false//删单条
$ d2 R! e: r) ^* H& \ - ]);
# n; A( @& B- p5 L7 x- m- t - $collention->remove([]);//删所有
复制代码- 新
) L# @1 x- d2 b7 h; `+ N% N) ^/ t
- $result = $collention->deleteOne($condition, $options);7 S0 e# J) G7 P; i5 [2 h |
- $collention->deleteMany($condition, $options);' g# R {% h0 J2 }1 W
- 3 |1 }. y q6 I% L) ?
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
' G+ S; l' w* F$ P5 Q4 Z - '_id' => $tableName//我在自增表中用其它的表名作主键
- ~9 d+ X! b4 Q - ], [) B: s+ c$ U/ A4 r) t5 w. _
- '$inc' => ['id' => 1]//自增
. y/ h0 S, h; ^6 e7 B - ], [
\2 u& V4 y. d+ k" e - '_id' => 02 H% y- A1 P0 C$ N# ?& l
- ], [7 \; }2 x- P1 \% e4 P
- 'new' => 1//返回修改后的结果,默认是修改前的" K; [. H; O) {
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
, T: v; x& V$ z4 y- Z9 Y1 r7 |3 t - '_id' => $tableName
* P" u9 d1 Y# q% K" \. H, g - ], [
) B; T7 e7 V5 X9 D2 \# v2 T - '$inc' => ['id' => 1]
: ^$ ?. a: {6 u# n0 u; k% j- A - ], [
+ m) R( k9 ?2 S* a0 `, e8 X - 'projection' => ['id' => 1],# i! |$ @: v; L3 Q1 z$ W
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER* A V$ h+ ]) C: C: s
- ]);
复制代码
* F- f& i4 u) R* D7 [- _, l: l( z1 H8 T. F7 K4 z
|