使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php5 K L& t! I: X9 L) T% D
* n- M, V, m# [# `- use MongoDB\Driver\Manager;
: D! M. U9 R6 {$ z2 A7 N* v - use MongoDB\Driver\BulkWrite; L S1 h9 }( ]! g! x
- use MongoDB\Driver\WriteConcern;
3 U* ~$ @# E5 D3 @, y! {( K - use MongoDB\Driver\Query;! E0 v8 c' F8 j8 ^) S: H, E
- use MongoDB\Driver\Command;" D- W" N( L& V
2 N* w* s6 q7 w- class MongoDb {
+ {9 w2 C8 O- [, P2 _ - $ ?' Y( }) [5 E: E3 H
- protected $mongodb;
: ]$ ^% w+ ]! r8 C5 b# n - protected $database;
+ F3 ~- k' ~8 r2 s: n/ D9 E - protected $collection;) q' U3 J7 _8 `6 z2 r4 J h, @- d
- protected $bulk;
( K; z' y, Y; e8 y - protected $writeConcern;) G& T; [' y+ `' G1 m1 K
- protected $defaultConfig
. |# U0 j. f1 r - = [
# u) F/ J( i- y; I" |. V - 'hostname' => 'localhost',
! W+ m3 k; ?( b9 W! t7 q - 'port' => '27017',
% Q$ P. i- k, P* F* X - 'username' => '',3 L& q$ ~; d* W3 |* M! V
- 'password' => '',
7 H4 f& H$ y) K! j& j6 ]! N - 'database' => 'test'. t! Z& @3 ^ E! q; O
- ];0 p, T7 C- W; E9 r+ k
- * v @8 [# w- L- F! M. i
- public function __construct($config) {# Q+ k, G' u* r& K- t
- $config = array_merge($this->defaultConfig, $config);9 I1 p# f$ I# V+ q2 h! X
- $mongoServer = "mongodb://";
3 {5 z2 z" q: Y g: X K0 N/ Y - if ($config['username']) {
E9 E0 a, Z7 T' D v' e; F0 ] - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
+ H @8 S( {( h - }
$ y2 f7 I: m m" h* g - $mongoServer .= $config['hostname'];
9 d5 T2 T2 U4 r E/ f& c6 ]+ H- R - if ($config['port']) {
3 M, r) j5 h1 q+ s4 O# j2 Q! W - $mongoServer .= ':' . $config['port'];
* b9 O2 B9 A, U a5 d& V6 o: G$ X - }
2 g8 y( u/ s/ `- C - $mongoServer .= '/' . $config['database'];. K/ r( ~0 U9 C3 I1 ^( {
- . ]# F1 \+ G6 c: [9 a
- $this->mongodb = new Manager($mongoServer);
0 ^% N. c& H2 b' S# {# ^$ ~$ d% D3 ^ A - $this->database = $config['database'];4 w0 y. ?* t, P
- $this->collection = $config['collection'];
( h1 K- n5 H# G" ~" |( E8 k - $this->bulk = new BulkWrite();4 _* i0 u1 S. z# u% F! q1 Y
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
8 U3 ]: T$ K' x! n - }8 E. K2 A. i; r8 U+ I
* _: G, j# J5 a' M( t1 Z5 j) H- public function query($where = [], $option = []) {* u' \% P9 G' X" r& f4 v) f, q
- $query = new Query($where, $option);
2 G+ _7 t0 L% h$ W9 C/ o& X( p$ J( q - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);1 w- l1 l3 M6 ^* U% }
7 o8 V" U5 @3 E4 T, k- return json_encode($result);" K2 g5 f6 L, y0 i& K. C. W
- }" ]' J7 l% U3 h4 y9 `& u2 U
3 W* M. F/ L. `( m3 S- public function count($where = []) {
4 @* L4 D6 ^% z# i# a/ } - $command = new Command(['count' => $this->collection, 'query' => $where]);8 W5 X. b' H3 v' W3 E. m
- $result = $this->mongodb->executeCommand($this->database, $command);
, {: [0 o* F2 T7 |$ M - $res = $result->toArray();- [6 Y0 w, X7 z. ~" V
- $count = 0;+ s1 X* V2 d& U+ V
- if ($res) {
* d& f( ]0 I. U - $count = $res[0]->n;$ e0 x, o6 S( W& k6 G
- }
6 x: n7 S s6 M- c
: ] \; x# r* ]$ k# h4 M- return $count;8 q# B) H6 C5 S( p! M7 ~' A4 ^
- }2 `- K) e* O c1 k9 V) A
; v% f% j* Y- {* x D7 p- public function update($where = [], $update = [], $upsert = false) {
/ }, d# e& u: ?6 k( q4 f/ ] - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);5 q0 k N# f% Z6 ^: N- @/ |
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. P* \3 }. m/ l3 [. [ m: p - 2 n+ U8 O# {# T% {6 |( D5 ]" e
- return $result->getModifiedCount();( t! G4 q3 f3 x3 M! i& r0 z- z
- }* Z% f; ]2 w3 Q5 y
- 4 z/ q2 X4 W4 E1 V8 I( j
- public function insert($data = []) {) }$ {9 M7 B: b- f
- $this->bulk->insert($data);
& {) Y% X) t6 Q6 M { }5 J - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
0 [: A2 |3 k, y/ L0 _+ W. V' I - q! z4 Y4 `' a& X) l2 H7 o9 V: @
- return $result->getInsertedCount();
2 y1 _: p7 b8 l3 W* { - }. u7 x; f. P1 E; W& D G" T
- # | L. H6 B' g4 g& _
- public function delete($where = [], $limit = 1) {
P6 A: g5 b& A6 n! j - $this->bulk->delete($where, ['limit' => $limit]);
5 L1 V" q$ J& \; E - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);$ h2 t/ {' M1 @: q/ X
- ' e( S' r4 P) N& \# p
- return $result->getDeletedCount();
1 z7 L; Q' W6 o8 J( \, \# I2 U - }- s. V+ A6 W/ z4 @: r
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原7 Y; R# V# }0 [3 b- ~. O7 V) Q1 q
2.新增- 原
( p# P4 h8 t8 u$ |/ x$ u
- $collention->insert($array, $options);
复制代码- 新" J: x& p. k$ }6 o- O# J0 ~% O
- $resultOne = $collention->insertOne($array, $options);//单) m% l4 m7 T* T0 |
- $lastId = $resultOne->getInsertedId();
9 u" d E5 B1 @0 k8 u) P - $resultMany = $collention->insertMany($array, $options);//多
& b+ @( j6 T/ e8 C - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
$ X& F; J4 i9 j* ?+ I2 M+ {
- $collention->update($condition, [
5 P' s7 Y% N. f- | r6 | - '$set' => $values8 w1 }2 ?( s2 R$ U r% A' _0 F
- ,[
8 S1 m3 a( F" n4 A+ Q6 j: h; O - 'multiple' => true//多条,单条false' T& D1 C1 K/ o" {+ @
- ]);
复制代码- 新
$ Z: n; D' a* k- _+ Y0 I+ T
- $collection->updateOne(6 ^' f7 N# W+ K. A0 t) J
- ['state' => 'ny'],+ v9 d' p1 ^4 S. Z% a
- ['$set' => ['country' => 'us']]
7 f, b3 ?: e& Q: c T5 k# l - );: m) m4 S& v, N( e
- $updateResult = $collection->updateMany(, I% N2 d, G5 C, x( l
- ['state' => 'ny'],
% |, y3 q$ m' }" c0 E0 d4 X - ['$set' => ['country' => 'us']]
6 [9 u; K* [" a& n; J$ [- b2 }' @8 C* ? - );9 I, o4 F7 t8 w5 U6 B7 r0 ?
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
, D6 |0 |) X( O$ @+ H" w3 _
- $cursor = $collection->find($condition, [% y3 q J) r$ T" A9 U
- 'name' => true//指定字段
0 y( ?; F- a/ @" u6 B; U# D9 o! b( r - ]);
( e8 y/ D! k# p( q" y - $cursor->skip(5);/ l" b, P0 s, \
- $cursor->limit(5);
3 V& H- r% ^8 {' B - $cursor->sort([
5 y$ q4 ]; y4 {7 M5 D - 'time' => -1, |+ M, s1 M w: [0 z
- ]);
复制代码- 新' M$ k: S) R/ F4 W$ H# l. ?
- $cursor = $collection->find($condition, [
5 c! u: U* j6 s; d - 'skip' => 5,
4 J( @( q8 }3 B# Y5 X - 'limit' => 5,
2 c& `& Z# X2 B - 'sort' => [
- L- r& T9 e1 D4 { - 'time' => -1
+ q* w" a+ u# v/ }, V# e2 l - ],//排序
2 k+ T t. y; f6 r" P - 'projection' => [
2 Y* U! L/ W B2 { - 'name' => 1//指定字段
}: d: l3 w+ c& }+ O( ^3 _; R) F - ]3 D# D' R8 H1 S* x0 g" E! i
- ]);
复制代码 5.删除- 原
. h' ]6 P# X4 A; p* Q2 p: O
- $collention->remove($condition, [
1 {& k% U% P$ n8 A - 'justOne' => false//删单条
5 z$ ]4 }: [8 z - ]);+ c2 B$ s2 j4 F" s( \, h, ~6 t
- $collention->remove([]);//删所有
复制代码- 新
1 [% h% @& y- A- z( ?, \
- $result = $collention->deleteOne($condition, $options);
! U& x v" ]& P9 Z* p+ k - $collention->deleteMany($condition, $options);
' i8 P) k" M s1 c5 ] - " [% y/ s- Z0 Z5 F, X/ ]! f
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
* B1 Y$ X+ Q) D/ @ - '_id' => $tableName//我在自增表中用其它的表名作主键 z& \8 h7 J( {5 W9 |+ c
- ], [
0 e& F2 Q2 Q; K4 V0 d) f6 N$ y+ O - '$inc' => ['id' => 1]//自增% R: M6 H4 X% z9 n2 {# j. B
- ], [4 `+ R9 N: d) A: a4 u
- '_id' => 0
" u4 F, b9 r7 T - ], [
' @! U' g* Q# l - 'new' => 1//返回修改后的结果,默认是修改前的
3 e1 Y( O& E. | o, j; u0 v - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
9 i+ C# H' a3 B" z* R6 F6 m - '_id' => $tableName
. V6 k+ D6 k, Y6 s9 k - ], [$ w+ c6 W+ {+ [8 H; B' q
- '$inc' => ['id' => 1]
4 w( Q3 h' @. H2 U, x - ], [* ?- j& ^7 M7 M1 X: w. r. v/ w
- 'projection' => ['id' => 1],1 E) K/ `( E8 {1 B# i v$ ~+ Z
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
; l- J: Q0 e2 o/ X8 l# J - ]);
复制代码
7 C% @1 P! ?( h$ x+ {0 w8 e1 H, P$ s
|