|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
# v% x D% a: U* P - 6 L7 w9 H1 i. R1 F" B. n
- use MongoDB\Driver\Manager;/ A: I% F9 X0 x
- use MongoDB\Driver\BulkWrite;! U* `0 `$ |; z* m: `, L" z
- use MongoDB\Driver\WriteConcern;
3 U& e5 ]$ F# i1 s4 ? - use MongoDB\Driver\Query;
; c9 y/ p6 b2 P$ Y# ^ - use MongoDB\Driver\Command;
& E$ l6 K/ l! i- G! o; U - 2 R) A' v9 ~" T; {& D9 _& C3 K
- class MongoDb {" d* @ C9 ]6 r5 U+ f7 U
- 8 d; }* }5 E l: J, k2 F
- protected $mongodb;
1 V! [* R* P* s3 A3 C, U - protected $database;
' Q9 z. n0 ]/ v - protected $collection;3 Y' T% Y! n& W4 J/ w+ `9 k
- protected $bulk;
+ o; u# Y6 Z7 ?$ ^ - protected $writeConcern;2 P5 V" x8 B9 r" j2 v. T' a& C5 D5 j
- protected $defaultConfig N8 B1 k, g; `1 v
- = [* J/ |( F2 ]5 a! e2 v$ A g
- 'hostname' => 'localhost',4 S. S# `' C N3 K X6 W/ ~
- 'port' => '27017',
' H" [+ t2 Q$ {8 D+ u - 'username' => '',
' o) A% x k5 O% w1 m - 'password' => '',- @7 t) k% Q) w: j3 {1 T. E
- 'database' => 'test'
1 w' D0 {& M) N - ];% _# s( S! F5 k' H
- / y Q5 K; `4 _
- public function __construct($config) {
' T- {' ]8 Z/ F8 c/ n1 v& L - $config = array_merge($this->defaultConfig, $config);+ b' w; u* J: f2 Y4 f" c
- $mongoServer = "mongodb://";
! T8 F. d2 a t7 e6 K2 q% B: J - if ($config['username']) {& B2 B: w1 Y( S: F( o5 Q4 v
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';3 k0 N/ [* V# s3 {6 s- S) N
- }# {6 j: I) c5 Q9 A1 T" I
- $mongoServer .= $config['hostname'];
' I. `9 _4 @- X {" p8 I4 G - if ($config['port']) {
8 j8 g+ ]0 k }. b$ M - $mongoServer .= ':' . $config['port'];
9 Z( D [5 M- n4 J1 G - }
" Q4 |' }) g; }4 ^1 P - $mongoServer .= '/' . $config['database'];
a1 W/ ~# Q5 p0 m! T
; Z! S5 J6 D' F- $this->mongodb = new Manager($mongoServer);1 U, q! O' W' b3 n
- $this->database = $config['database'];/ M7 N$ f3 z# a( L% M
- $this->collection = $config['collection'];% q7 ~* _; u# U
- $this->bulk = new BulkWrite();2 d9 J* N: r+ K* U6 P5 A2 i
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
& u! H% P, `3 e$ r- P9 H& T! d - }
8 k1 r+ P+ y0 O% D' E* Q
7 D. d6 _4 f. ?: j, C- public function query($where = [], $option = []) {
& Q6 o& n$ P" l! A( _& o6 d - $query = new Query($where, $option);
9 d4 q6 R" n$ m& S - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
! i2 H ]2 z/ T2 U7 R6 ^# t& H0 _# m6 p7 f
1 {1 Z6 T* C( L% L8 v- return json_encode($result);
2 S6 j2 i% b! ^. q - }2 k) B6 U0 O* L% x4 N
1 _. d. z) B: l) l* w. w9 V4 \- public function count($where = []) {
6 `, T1 o, i+ @" C# y2 j - $command = new Command(['count' => $this->collection, 'query' => $where]);
. i8 G( a, K; {4 Q4 K" r" K; t - $result = $this->mongodb->executeCommand($this->database, $command);
; N' {( i9 B; j4 q! ] - $res = $result->toArray();
1 A- s, ]' }- Z( u - $count = 0;* a- s& s3 I3 k& V- X( ~: }
- if ($res) {
$ P' R: I0 M1 D1 \. r - $count = $res[0]->n;8 A: s3 j* l/ i8 M) G" b
- }/ k- u7 R. K' g0 F
$ V3 Z; ~/ x0 d3 F+ ~$ o: H- return $count;
# J" \2 d$ ~5 J! @6 B - }
5 p8 h$ w* r1 d7 h) s' c - $ Z: K2 ~2 a. G; v
- public function update($where = [], $update = [], $upsert = false) {6 x" _1 a3 w- ~" A* f
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);! c* S9 I! {. G6 F. o( o( o
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);, f6 x( Y: f0 M
- 2 M8 I- e, Y/ x5 h: d0 _0 ^
- return $result->getModifiedCount();
8 s }4 r) Z/ S: {6 L7 i, Z - }
6 Q; `. e9 z2 @: `/ f: I; O: M- v
) l; K; N; p# s/ C( l, T- public function insert($data = []) {+ I/ Y4 c7 @- [- [; ^9 Z5 A' s7 L& i/ w
- $this->bulk->insert($data);* j% R- o4 \8 k) T0 o# }
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
0 W+ f2 y' {+ F
" [( I0 o6 x. H4 y$ q3 G' y" C- return $result->getInsertedCount();0 v' r4 `, X! G7 L1 a M. K
- }
! B/ {* O( R1 ?$ l4 o) [ - + \+ m8 [, a( E$ i; [6 l5 o/ G4 }
- public function delete($where = [], $limit = 1) {& C: Y2 ]; x4 i
- $this->bulk->delete($where, ['limit' => $limit]);! ^" w+ {3 O3 N1 k7 b% i O0 g
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
1 L) K, c7 _; o
/ e" P6 F" v, j0 q$ U: P- return $result->getDeletedCount();
4 o) b3 n, i4 V& U8 G- z - }
' W; K) X/ z$ z0 n2 J - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新
* y" H) l9 g+ }0 o5 K2 x( J 2.新增- 原: h1 Y1 j) B! t; k" S% o
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单/ K% F) P" a& A+ r& Y
- $lastId = $resultOne->getInsertedId();
; Q3 G9 x( {! N9 ~0 ? - $resultMany = $collention->insertMany($array, $options);//多
, ^3 s5 }& Z9 G; } - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [8 Y4 l7 l; A/ ~5 P
- '$set' => $values
$ |+ x7 y7 G" T( d* q" C' i& Z) U - ,[5 g9 P+ J' U( p4 }$ p2 _
- 'multiple' => true//多条,单条false7 }* { N3 W+ b! |1 Q8 J& u
- ]);
复制代码- $collection->updateOne(2 u8 ^) W4 ~1 j; u
- ['state' => 'ny'],+ Q+ F9 Y: N" {3 I$ a+ o
- ['$set' => ['country' => 'us']]
8 E! W- @- j- o - );, x, Q0 f; ~7 y
- $updateResult = $collection->updateMany(
5 T0 @; f4 Z+ q) P - ['state' => 'ny'],0 t- [$ g- o' C8 Z8 x2 A
- ['$set' => ['country' => 'us']]' o: U* Y* _: \) M+ S- F# i
- );/ H) D3 K# e& l% S! F
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [5 ?2 G' K& g8 X& e
- 'name' => true//指定字段" Y0 T" P9 `8 ^" \
- ]);
, U' Y) V. S; e6 y- [6 J3 c - $cursor->skip(5);6 u5 a7 a0 _* m8 D( j* Q
- $cursor->limit(5);! a1 N& h" O: I( m& R
- $cursor->sort([
g. q5 a, P0 v$ I - 'time' => -18 I, T- Y. L; I' i
- ]);
复制代码- 新$ Y8 O: |* U/ y, a: {0 i. j7 E$ i
- $cursor = $collection->find($condition, [1 q7 g; @, h v5 r2 o
- 'skip' => 5,' `2 R/ o5 h- H2 u6 M6 C6 n
- 'limit' => 5,9 j# x9 K4 z/ p T6 h
- 'sort' => [9 P- U! r( j. }7 i9 a$ P# }
- 'time' => -1
/ K5 @8 ?' s% m6 S G& ?# A! V - ],//排序
' ^! o) [4 b3 a! { - 'projection' => [
6 |' s, I ]+ g - 'name' => 1//指定字段/ t6 ?+ ^, D6 y
- ]
$ V$ a: E1 ~$ y: D; ] - ]);
复制代码 5.删除- $collention->remove($condition, [
9 q1 d1 K- k+ {$ a4 g1 I+ D3 s1 q - 'justOne' => false//删单条: r4 a7 I) U, d3 s- N f$ E- z6 ], [9 L
- ]);, M- U( n/ D8 s! N, P4 Z- R* k
- $collention->remove([]);//删所有
复制代码- 新8 r2 Q) i. j8 E3 F7 T, K* e! H9 L
- $result = $collention->deleteOne($condition, $options);7 p1 s& e% k* `* i0 p
- $collention->deleteMany($condition, $options);6 o) {+ o' o# q9 B/ \1 E7 {% W
- ) ?; _0 r) m- V2 R( ^& ~4 Z
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
- J' @; k$ p% T, I8 _ - '_id' => $tableName//我在自增表中用其它的表名作主键3 c5 X, X( _6 G2 L% P2 }
- ], [* Y+ H% K* {7 o1 q) L# f
- '$inc' => ['id' => 1]//自增
3 }( V$ r1 _" `$ D7 r' r - ], [, z# s8 b9 }5 {6 U
- '_id' => 04 S/ o% P0 c5 Q4 k0 b7 k- B" d
- ], [- H0 d" K, w# Q3 L
- 'new' => 1//返回修改后的结果,默认是修改前的) ^. }0 T8 V1 T
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
; P% M% N4 z) R8 c9 N/ ^' N - '_id' => $tableName8 ?# H. ~+ r6 y$ z$ N
- ], [
8 N( N! M# s* _' l \; S# ]9 c - '$inc' => ['id' => 1]
( V3 j" s6 R& G, k( E" ? - ], [! H) K" }9 T6 c- f5 G' `! j% l
- 'projection' => ['id' => 1],$ u5 o1 E y9 o* k4 S) \
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER; @4 A$ u: A5 r& P5 X
- ]);
复制代码
! C5 L% n, F& k( P9 ]7 J w4 P/ C% _0 n8 ?9 F' c3 k/ H
|