|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php2 q# o; \& d6 g$ n7 Q7 |# W7 g6 f
- 5 t- _9 x# K( a9 m+ s1 k5 ^
- use MongoDB\Driver\Manager;( k) ?0 S$ I: S, x; ^
- use MongoDB\Driver\BulkWrite;
; R0 ~: D8 {9 f' {' G. B$ A - use MongoDB\Driver\WriteConcern;% {7 S5 c9 }, o; y0 n7 K% ~7 n8 U
- use MongoDB\Driver\Query;
! o* F. L4 N5 a" D, P, i - use MongoDB\Driver\Command;
1 W0 Y5 z5 I/ y. P
' i0 u6 u: \) ?2 X2 y& ^' A- class MongoDb {9 W9 `( u- [7 O5 p
7 B# z; z2 d; u, Z8 I6 I# G2 R- protected $mongodb;& W: D5 t2 p$ G9 W; z! g6 A
- protected $database;
6 D: r5 c8 l- e - protected $collection;- A+ i* D# i7 K$ }% }4 v% @
- protected $bulk;( V7 X5 r: N* C5 x# Q2 x6 e
- protected $writeConcern;
( w" p/ W( i4 O: p7 V' o# ` - protected $defaultConfig( O x3 m- f5 z* u; Q
- = [
5 r& }3 X( j1 Y% A - 'hostname' => 'localhost',6 w9 [2 r* ` _+ f
- 'port' => '27017',5 Z5 V7 A1 }9 `) {2 b2 X% e& ^, g
- 'username' => '',! W. c/ {% ?. u- A R8 o C
- 'password' => '',, }% k$ X& x% T: v$ Y9 a5 l3 ^
- 'database' => 'test'
0 L) ]+ p1 d! e - ];6 U" i, y$ _9 q- i$ F+ G7 A! g
5 X! V( [ J7 U: C0 w Q- f7 R- public function __construct($config) {
0 [/ ]! A5 u& [ - $config = array_merge($this->defaultConfig, $config);$ B. ?$ c- @& B; P6 G% h/ }
- $mongoServer = "mongodb://";
- @- X3 k, r$ I, Z- A% { I, { - if ($config['username']) {
; Q' E0 s% W1 l - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
3 D8 T" v2 i1 M+ s6 q* s5 g - }
+ ]7 Q4 _) l8 ?; m' O4 t5 L - $mongoServer .= $config['hostname'];2 K4 [0 Z3 y0 ^3 c" w' ~/ K
- if ($config['port']) {
& M4 T. Y* A. [6 F- Y9 J7 [ - $mongoServer .= ':' . $config['port'];
; X0 G4 x2 T& e* v- q4 S - }2 X1 b% W1 _$ Y9 `+ V% w
- $mongoServer .= '/' . $config['database'];
5 S7 L/ ?, h7 q# Y2 S* B( { - / p/ Q; G3 o+ ?1 b# y
- $this->mongodb = new Manager($mongoServer);- I3 l# g- S8 g
- $this->database = $config['database'];
% v, P6 c$ ?; s: J" X1 D - $this->collection = $config['collection'];
1 e& W7 m& E5 s: y, @+ w# F - $this->bulk = new BulkWrite();
' ^' l) N! q% l4 Y0 E0 \, R$ R1 @ - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
) I @4 @% l A; l* V - }
+ W" R% _8 S% a9 y
) K0 Y d( |, Y6 k, G F( L- public function query($where = [], $option = []) {
1 t- ?( z4 M8 I; p' Q - $query = new Query($where, $option);
f3 U+ {$ k: F+ z6 T - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
- d* p' w4 E& B" l0 L. u
* I$ X8 U \. A- return json_encode($result);
5 n0 ^: J/ O+ d8 O7 O' E/ F! T6 T - }/ R+ M. y& y1 B/ o( X8 U, z, z
- % G$ M2 q2 {0 O( x: H9 s
- public function count($where = []) {1 n: l! H: ]3 b$ B! D& \) g' V3 t
- $command = new Command(['count' => $this->collection, 'query' => $where]);- x2 @# ?$ E& U0 [- f! W
- $result = $this->mongodb->executeCommand($this->database, $command);$ l! o# f- m; `9 R4 l( p
- $res = $result->toArray();
' `% s4 l* @: V - $count = 0;
z/ C/ Q" y/ E" k: F/ ^* e - if ($res) {8 q3 ?' d* W+ b2 y, z( L6 u! M
- $count = $res[0]->n;
' A9 T) h9 p+ S; N, n. \ - }( l: T7 f; a/ J+ j4 }3 Z4 Y* L
- 1 o7 Q. [$ u# C) O! w
- return $count;3 L; H5 m: X6 @1 q2 C* {
- }
+ P* P: a" b) T& W# i
' s6 w/ l0 i1 b& x- public function update($where = [], $update = [], $upsert = false) {) y( M- K. O1 Y. |
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);4 i8 ^6 U E2 p1 G" l$ ?
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
. K1 y7 q/ B% q - . m) g4 G% _; o8 ?# S
- return $result->getModifiedCount();
, c7 y$ d0 F4 V( o - }/ G6 c# [- T1 P/ N2 u
3 _5 }6 q \4 C" c4 @" w( c- H- public function insert($data = []) {
) D1 m8 X7 n; T( z( f9 S - $this->bulk->insert($data);
+ Y$ T0 W& A) B; j/ L - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
: P' V/ h+ |) j+ m! ` h/ Y5 n! T0 V - % f r- r, k4 B- J
- return $result->getInsertedCount();2 J6 s2 p+ e1 N* u; K
- }
3 j7 D9 A# \+ u5 W - 7 [+ o6 i8 I* Z/ D0 u$ O X
- public function delete($where = [], $limit = 1) {+ {# t4 m/ ^7 Q" _- `6 p
- $this->bulk->delete($where, ['limit' => $limit]);8 W# _! C7 e! X$ S r$ v
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# z; [5 {: K* \2 g) ] |/ q
- ) E( _4 v3 M4 o2 m# L
- return $result->getDeletedCount();7 |5 b1 t1 Y( R: v* z+ V6 O
- }
4 l* \. i$ G! v5 j7 d - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
. O6 A' R- F0 l( R/ j. ` 2.新增- 原 `, X! s( p- q+ B1 J0 P6 x& G2 E
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
+ W, U- F. f# S% p- P0 Q# t* K - $lastId = $resultOne->getInsertedId();
2 C- V# Z+ U, X' ]2 c( T h - $resultMany = $collention->insertMany($array, $options);//多
3 }2 M1 Q4 v, C- Q5 O( k# w. X - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [/ F, R, N. `: g9 ^
- '$set' => $values
# ]- I: q; O$ [3 U. s - ,[
$ E" t; J" h3 A' _% P - 'multiple' => true//多条,单条false
! r: z& H% Z' P; s1 ~ - ]);
复制代码- 新
/ i8 ^% ?1 V. i: T" M3 n7 T5 Q
- $collection->updateOne(
- [" ]' r6 h$ u& a - ['state' => 'ny'],
2 P5 X( ?9 [+ i4 C$ q - ['$set' => ['country' => 'us']]
4 g6 C x* o2 O' K C - );
4 q: n, ^8 `4 m2 X - $updateResult = $collection->updateMany(
* n9 r' I+ `/ m2 Q - ['state' => 'ny'],0 c) P Z! \* b$ i# `& T
- ['$set' => ['country' => 'us']]
$ i6 L; H% D5 T* G! Y! c1 z9 _ - );
% c* {2 C' d/ x - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [$ b% @, M/ U9 k% |
- 'name' => true//指定字段
( } Q& t r, N5 g a: p9 j - ]);
' c2 R# a* {: T; Y# _ - $cursor->skip(5);
: l: F+ A+ K# l( L+ K - $cursor->limit(5);
& g3 M. s! }/ N2 x' | E- j$ j - $cursor->sort([
7 M$ E/ |0 t: v _/ K" N - 'time' => -1
+ }3 h" F8 [ X5 j: S - ]);
复制代码- 新
( z9 U5 e7 u) w) ?8 X# ^7 Y
- $cursor = $collection->find($condition, [" [# r4 V2 q2 ^' t; x" j" Y
- 'skip' => 5,
6 q0 T" b- x8 n! B* H - 'limit' => 5,
5 h L7 u7 y. X - 'sort' => [
' j; O$ @5 x' Q9 {0 V6 B+ z - 'time' => -1
) M2 T$ G; ~ V2 l" s* } - ],//排序
; y0 s) J& ^9 S7 E - 'projection' => [
. u6 p( E- e. O7 q& U - 'name' => 1//指定字段
, J& _/ H+ |- O3 g$ [2 T - ]
$ z, t+ M; C# r* L7 r - ]);
复制代码 5.删除- 原
- m L# _% D$ D' E' L$ ]
- $collention->remove($condition, [
; S( a- L4 ^1 p - 'justOne' => false//删单条; J; z+ c) D3 O2 m
- ]);5 j9 v' o3 S& z
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);# @* P! @) I$ P/ N
- $collention->deleteMany($condition, $options);! Z# V. {: P5 b0 k) z* j
7 u' z' q$ \4 ^- d- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([( _, l: x5 G+ X4 }
- '_id' => $tableName//我在自增表中用其它的表名作主键: v; S" ]: }6 G
- ], [
: s. u) h5 r" {( x - '$inc' => ['id' => 1]//自增: {( C( y! n$ e1 a
- ], [% u9 _5 P. C2 k$ _% R* l
- '_id' => 0 i: K S& `& a2 V
- ], [
% V3 g! d3 e# T, O- C - 'new' => 1//返回修改后的结果,默认是修改前的$ `' A, ~4 T) j
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([& t# o- m; ^3 [' R/ _- d6 U5 G
- '_id' => $tableName
Y0 \, n4 t5 ^: a& f3 o - ], [
- o1 N: e, y4 B4 N: I3 `; H: @2 e* ^ - '$inc' => ['id' => 1]
7 b ~2 W9 H+ \2 p/ V7 L( V7 L - ], [
- [- Q$ g3 {5 Y8 p+ ]6 @1 Y9 c - 'projection' => ['id' => 1]," f: f- H5 I @4 m& D
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
$ L+ \2 J9 ~/ G: J7 Y" P" s, w7 X; f - ]);
复制代码 ! A7 C: Z2 {0 L4 a2 F g
( u8 @+ M. ^6 M9 J; P
|