|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
1 @% y4 A* a4 M' u. |
, z, ]0 C8 P6 P. J9 p# ?) K- use MongoDB\Driver\Manager;
w3 I5 L5 @3 T! R5 L$ ^ - use MongoDB\Driver\BulkWrite;
: K0 \8 d5 X+ P& c- M* \ - use MongoDB\Driver\WriteConcern;+ l' E8 w. n# K. v. z
- use MongoDB\Driver\Query;7 q6 r4 n& H1 J7 j, B; q* k
- use MongoDB\Driver\Command;
) j! K4 j: P1 X
: Y8 p" I1 B$ r2 |- class MongoDb {- _- d3 Q5 S( A! P) t
- 9 x/ R8 C$ v4 S8 e. O
- protected $mongodb;
- M& e9 H* |# A3 d* b - protected $database;6 W$ X- x7 I- d9 p3 K/ q' q
- protected $collection;
T3 [! z' e4 R* G - protected $bulk;
* v' [9 t9 c+ Q1 r - protected $writeConcern;
# P7 [1 u. `! P" F% [ - protected $defaultConfig
; I, i: P9 ?) p - = [, M+ T6 v g. N0 c& B3 j3 H
- 'hostname' => 'localhost',4 l, J5 y* K$ u/ V
- 'port' => '27017',* i- _8 P. h, ?
- 'username' => '',
* b w9 r/ e% |0 l) c4 b4 ]& w; ~- E - 'password' => '',
+ _& g( j0 T. Z* v6 n - 'database' => 'test'. M+ a" _( [ Y0 R2 [4 q9 r' x7 w) J
- ];8 `# ]% }0 K) r
- 9 X: W& O/ Z8 ^
- public function __construct($config) {
' I V0 H4 y N - $config = array_merge($this->defaultConfig, $config);
# {% u( S* R G1 D - $mongoServer = "mongodb://";( ~' U% s9 Z) }9 P' z
- if ($config['username']) {
* R' \1 y$ a# L, q - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
! F$ ^8 K& @% W - }
& A2 h! ?+ U9 ^; ]2 u6 q - $mongoServer .= $config['hostname'];' e+ A, }9 J( F: C# i7 y! s
- if ($config['port']) {
C% I$ w& S3 ] - $mongoServer .= ':' . $config['port'];% M: I$ r0 `, o3 u% C" n1 H; i
- }$ f' O2 l; q: k6 o9 v
- $mongoServer .= '/' . $config['database'];
; A$ h% h: x$ b3 H) R4 ]3 i7 w0 ^0 \% c" H
$ i8 u. O0 j" ~& F1 m- $this->mongodb = new Manager($mongoServer);' k2 a9 |% G+ N9 Y9 F! ?! Y* X
- $this->database = $config['database'];
+ b+ h0 O: u4 I - $this->collection = $config['collection'];2 o2 m# ~5 ~6 G! L$ D! o' j ^
- $this->bulk = new BulkWrite();
1 v" s3 ?( t) K. X3 [3 q - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);; n+ g7 L/ t2 E& b+ S6 f: K. v. p3 |
- }
- q5 B& R# F' S2 n- ~. }$ j j
) H, Z( R( w8 c3 X* N- public function query($where = [], $option = []) {& \3 l) F0 _- L& A$ m
- $query = new Query($where, $option);# e4 s, Q y8 S+ ]' N4 Q K
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);! Q+ c3 a; S1 l7 [2 [) y# s" u
4 U# T, q3 l: p2 U- return json_encode($result);- T, J, g% N2 G
- }1 P$ P" g" j$ n6 ` E: p' h
- ; V( T0 k1 H' A7 g& E
- public function count($where = []) {
3 D. |9 Z5 H7 m3 c! P5 M: I0 c - $command = new Command(['count' => $this->collection, 'query' => $where]);5 T; w0 c: \: B, }6 u0 {- F% |" Z j
- $result = $this->mongodb->executeCommand($this->database, $command);
0 f; I5 Z$ `* X% p# Z - $res = $result->toArray();- ^. p" z6 q1 n7 Q8 L* a
- $count = 0;! ]6 Z/ [; C. O
- if ($res) {
) `6 K. C! l# Z8 _; @ - $count = $res[0]->n;& W W& l D. s( P; M
- }5 j/ [1 n: ?3 t9 n7 K& v8 {* B
$ _7 {) e) p$ `6 |; I4 ]$ h- return $count;3 E- U: F, D# p* E6 V1 H
- }
5 C3 n0 t/ a" e/ |' f5 p1 W
! T+ G9 N* M+ n; D( \& v' b- public function update($where = [], $update = [], $upsert = false) {2 q8 l( A2 K9 r4 e/ j5 V
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);( i9 Y# w! I3 k# R* _
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
$ B; s# c+ y( o5 {" H r - ' s$ R- a# f( k7 K
- return $result->getModifiedCount();% T4 K9 u/ v6 D- |" m
- }; z" J7 q' [; B; t' _$ I, Y
2 w+ m/ d& j, y9 k; [- public function insert($data = []) {
( U- }& e6 F6 X - $this->bulk->insert($data);+ E0 N1 W, Y3 z% m3 d$ N
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( x* j6 e9 S S/ {; r; W% ~4 [ - % D; o8 t) K. t
- return $result->getInsertedCount();
, H7 `) M, K* Q: y4 g4 y- z% n - }& Y( L2 }: K* W5 }5 E8 D
- % ~" j! y4 T9 q6 [7 m Q0 q! v8 `5 F
- public function delete($where = [], $limit = 1) {
3 ~$ I9 s& x$ w. J - $this->bulk->delete($where, ['limit' => $limit]);0 u' U' U6 a' i; n6 S0 q, F' |$ l
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);) X: [/ {- @5 w7 }
- ( {$ Y4 o G5 }4 Q D
- return $result->getDeletedCount();* E3 U2 ~2 ^, Y7 B0 r% H( d" {+ Y
- }
/ o' [+ A) k$ v9 c* x- u - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
. c, m) a/ P9 O* S7 `- G* Z 2.新增- 原
! j# M8 ]0 R% Q6 U0 }+ c
- $collention->insert($array, $options);
复制代码- 新+ b& r" {3 t0 v" {! S/ a
- $resultOne = $collention->insertOne($array, $options);//单 m9 S) _$ ]7 s8 H, }- A
- $lastId = $resultOne->getInsertedId();
$ {% V9 A& Y8 | - $resultMany = $collention->insertMany($array, $options);//多; T ]5 t) d6 T+ h' Q: a$ G
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
[6 r7 Y) w- Y$ k6 g h - '$set' => $values
( E" \ ?; y: K2 A2 i - ,[! h% {8 _) s$ F# r q
- 'multiple' => true//多条,单条false6 z7 b+ e, V. u) m' R' S* J
- ]);
复制代码- 新
3 w* S0 v" H7 e* S& o) |! n
- $collection->updateOne(
6 j; [0 N1 ^# f7 b' H7 S F - ['state' => 'ny'],% J8 I; `# N7 N& V2 c$ u. d
- ['$set' => ['country' => 'us']]: J6 B1 f2 ~" k D. l/ O
- );: W( _2 P) I1 _% V3 k3 k! k
- $updateResult = $collection->updateMany() e* y# z) |! H2 Q) P
- ['state' => 'ny'],/ A! U- l/ A/ Q+ I7 X
- ['$set' => ['country' => 'us']]
# r1 ?% C/ d3 m. c f- j" w - );, S" W! I% J* O d& s V3 E" j
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [# E2 ^2 b7 f4 r6 c
- 'name' => true//指定字段
9 i# @ i$ X8 J% Q* m2 Y* ?% i - ]);
+ }! A" q6 j, n# b- g - $cursor->skip(5);$ E6 a7 q1 }1 q- }0 V7 z$ P) v
- $cursor->limit(5);
- q8 |; u& y m1 {& e5 t0 ^ - $cursor->sort([
, |% t% X$ v: V - 'time' => -17 ~1 S: C1 t+ x8 J8 Q
- ]);
复制代码- $cursor = $collection->find($condition, [
( H2 x6 q r" X - 'skip' => 5,# a# H" F6 O1 d! T) L
- 'limit' => 5,- B2 e3 x9 S6 W% Y8 J7 J6 i U
- 'sort' => [9 ~+ v4 u7 D; U/ H/ w; c
- 'time' => -1, H# ]- g$ \# @; y s
- ],//排序
" X; f. m" x2 r9 Z8 H6 ?5 A* a0 z - 'projection' => [! u6 ?% \/ p7 e' D# I
- 'name' => 1//指定字段1 S* V9 E: V) L, \1 g
- ]8 G3 [; A% O8 g5 {+ \8 r
- ]);
复制代码 5.删除- $collention->remove($condition, [
' L' l$ M4 L( w- Q - 'justOne' => false//删单条
6 J0 ^/ f6 j# J) U5 F - ]); q0 U' _' N1 {% p6 r, ?/ r: i
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);; r: F A; y ?5 E7 t6 V9 h4 e
- $collention->deleteMany($condition, $options);
2 T/ x0 Y% _% O# V! @" Y! k
, V9 p/ |% D) Y" a- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([2 C8 A3 G' \) b1 d% U; P% b
- '_id' => $tableName//我在自增表中用其它的表名作主键/ t4 p0 K8 Y Q5 D
- ], [
* b7 f k8 R0 t+ i$ C# ]' _ - '$inc' => ['id' => 1]//自增8 ^1 c0 t; [7 I) c
- ], [( B4 ?/ R# z* ~7 X$ q+ g* x8 P
- '_id' => 0- U% v% g9 c5 k2 v$ A8 r
- ], [7 H" @# Q* H! \: i/ ^6 i: D& m
- 'new' => 1//返回修改后的结果,默认是修改前的' W9 m9 `8 Q4 M% Q" v
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([5 E9 M* t2 J# h; D6 _/ b% P$ X) d
- '_id' => $tableName
6 A" s3 M3 ^: Q - ], [ `2 s$ k6 F0 y! z' R
- '$inc' => ['id' => 1]! Y, L+ ^+ Y9 Z
- ], [9 [# ~9 r- f- ?
- 'projection' => ['id' => 1],
# E6 R3 U. ~" D - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
/ T8 }. v0 s. [2 n3 [( { - ]);
复制代码 % U( A4 P L G. h3 B
6 x: {6 U' ]+ m+ D4 J0 {1 \
|