|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
7 f) m- Z2 N7 V - " K+ v2 f- L+ X& m) w
- use MongoDB\Driver\Manager;
# P4 Q: Y7 r" w7 M% J& b9 O. S - use MongoDB\Driver\BulkWrite;
c( w: D1 l4 D! z5 L( o2 a - use MongoDB\Driver\WriteConcern;
* h1 ^% x; B1 z, l6 K" y+ _: Z$ t, P - use MongoDB\Driver\Query;
$ o- k7 _% j) M: P* K - use MongoDB\Driver\Command;
- ]. o5 g3 A9 M5 j$ _
8 T9 Q( u5 C' O( U5 E0 G, V& W- class MongoDb {$ E9 |- Z# p$ d: R6 A
8 Q. I) Q) l) n9 J$ P. T- protected $mongodb;
; ~% A/ N6 Y4 B# V5 Y+ F - protected $database;
% D1 U! Q* f ^1 ?6 G( X+ Z; V0 R - protected $collection;1 L# r( q5 Q' j' L
- protected $bulk;
& L5 K8 |( C1 t+ w: E - protected $writeConcern;) G/ U* r& y( A( v8 [. q
- protected $defaultConfig
) @+ c* b B9 ]$ b* ?0 y - = [
# P: o C. v, C" L - 'hostname' => 'localhost',0 t2 K$ D" R8 u% Q
- 'port' => '27017',4 X% U3 d8 [' X& {1 k; E
- 'username' => '',* ~) V( N5 `# j/ e% |
- 'password' => '',
0 m9 u. W) N$ N3 r: h0 _7 F - 'database' => 'test'
) C: b+ x7 P% ^5 {6 H6 o - ];
) F4 f% Q8 w/ X' H2 T1 w
! ~7 y* \9 {1 D* D5 o& V$ C- public function __construct($config) {6 p. s& }5 L% }
- $config = array_merge($this->defaultConfig, $config);
' I! M, d4 ?) w# [0 L" u - $mongoServer = "mongodb://";
' G& X3 ^: J/ ~" A# l+ | - if ($config['username']) {; d# r/ ~. d! Q( c6 ]
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';9 @* y6 u0 @( z
- }8 d2 k7 D, I2 r3 _
- $mongoServer .= $config['hostname']; Q# l; ]6 h) I
- if ($config['port']) {4 w$ Y3 m" ~, f- ~4 Q9 x
- $mongoServer .= ':' . $config['port']; [: y" i" k6 P. h% Z
- } U& p7 I ~6 q1 N+ x3 W1 w
- $mongoServer .= '/' . $config['database'];
1 ?! t/ u+ n4 \! ?# Q. \ - 9 T) r9 p# K" Y' l7 Z
- $this->mongodb = new Manager($mongoServer);
& ^ B( j0 U# q) g - $this->database = $config['database'];
7 S' s) b$ S2 z - $this->collection = $config['collection'];6 W" `4 ]- k6 @* T! p q/ d& b
- $this->bulk = new BulkWrite();+ }$ w- X, O$ q/ d" l
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
7 }% u% Z2 |* O4 S. V* w! |* ^' V9 B - }4 v+ K% j" v6 T4 o) O( k
- 6 {. x* D5 a* f3 O1 y. [7 M
- public function query($where = [], $option = []) {
5 s9 C ]" i3 f' U - $query = new Query($where, $option);
3 B, V% e7 j! E3 N* C( D0 h - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
3 I9 S% x( ]3 }& [( s: \
+ O7 P: `0 V& P& C- return json_encode($result);. `. f* y; Y+ a( z9 O( U
- }! ? O# \3 j: d/ s+ P B- g
4 m( p B/ C( l/ a* N+ H% @- public function count($where = []) {
* ^7 R3 q9 j2 c+ I% V2 c! ?8 j - $command = new Command(['count' => $this->collection, 'query' => $where]);
9 i8 o7 H$ H. A - $result = $this->mongodb->executeCommand($this->database, $command);" n) Q3 U, K' |0 e
- $res = $result->toArray();% t: ?% ~ y3 D4 M2 l: l5 E
- $count = 0;: E0 a! R, i Y3 w" N' m1 ^" G* `! B
- if ($res) {/ ^0 ~7 w* o; v8 b( z3 w" n
- $count = $res[0]->n;
5 U/ f; n! C; [- ` - }- o$ K6 c2 W% a3 M, ]6 ^
, u6 M( N3 K# L: q; @- return $count;
2 u1 i5 T3 Y" j! y - }9 n3 e" \% j$ k: y% s% G
- 8 K. ~. u: V3 O# _' g, |( k
- public function update($where = [], $update = [], $upsert = false) {
" v4 ^/ p8 d4 Z/ z; n, F - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);5 R) z' a- p& M1 S% v! A
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
5 w$ Q# u/ D. n2 j' u - 8 G h8 a! q! a ^2 |
- return $result->getModifiedCount();
2 k8 ?5 K1 ] E- T; ~( ~ - }
5 m1 P) N/ F* I: f+ E# Z# `/ h - * O# b$ t% e t9 t# |. `
- public function insert($data = []) {, y7 D% j5 o! x3 q& l
- $this->bulk->insert($data);
9 b" q& B5 n0 M! v+ d2 W - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
9 o8 d4 g$ V7 t/ q& G
1 B# O. V* L5 h) V" s0 A3 v- R7 N- return $result->getInsertedCount();# X$ Z4 b r. S+ o3 k* s
- }
! Q" p9 C# N7 A. l" [6 P - & `: ^; R% E. f% m
- public function delete($where = [], $limit = 1) {. F) M" N9 N# Q7 Q
- $this->bulk->delete($where, ['limit' => $limit]);7 {% m8 N* S- _) o8 x) M2 E
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( M: N: H$ e6 P1 k4 n) j - 1 P+ g- a1 S0 D
- return $result->getDeletedCount();0 X! |4 `1 x1 p. \) p
- }8 ?. v% K* r% r) ^ d+ M
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新" ^( e8 N9 k. \0 v! I6 N
2.新增- 原4 e- S4 |$ J/ M- D: x: V# y2 x( e
- $collention->insert($array, $options);
复制代码- 新
; Q$ Q, }0 o) t' h9 J" e# Z3 K
- $resultOne = $collention->insertOne($array, $options);//单; f# l4 v0 ?6 w( E8 j! k
- $lastId = $resultOne->getInsertedId();
+ Z2 ]% Z! D* n - $resultMany = $collention->insertMany($array, $options);//多: ^! F' P6 t, t2 A- T6 @& Z
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [7 _' Y4 |" B; ^ b6 R8 i; |
- '$set' => $values6 @% x4 i% C$ H( G# R1 S9 H8 \" r
- ,[
- g, y/ v% g7 W3 s - 'multiple' => true//多条,单条false
* L, _: O, Q! I' `+ r, f" Z, d8 \% X - ]);
复制代码- $collection->updateOne(: M. I4 W& q! b) t' J8 y
- ['state' => 'ny'],
; n3 N x# T* o8 G* A6 X. X - ['$set' => ['country' => 'us']]. B% `$ d2 V ]" B) Y
- );
) H2 w" i1 m5 e6 A l8 C - $updateResult = $collection->updateMany(# }8 ?% n. `6 G. O
- ['state' => 'ny'],
! ^0 K6 Z% z) L9 o; Z \& Q2 {' l% L) L - ['$set' => ['country' => 'us']]# H& e- d7 f1 j/ r+ Z6 J1 W
- );3 X5 M: N# o9 m/ K5 N& h. h
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
8 Z) O; ]% P. |" l7 R v8 t: q U3 v - 'name' => true//指定字段7 I' w% x; B4 r* l5 c" j$ P- m q
- ]);( B, w% o0 n. n3 Z2 @3 r
- $cursor->skip(5);
+ [1 J/ D7 `' ?, u, T6 Q8 _ - $cursor->limit(5);( o u7 e' |3 C
- $cursor->sort([& A; d j. Y+ D! G( _. R* h
- 'time' => -1. D4 ?6 N0 B) Y( z$ ^+ A
- ]);
复制代码- $cursor = $collection->find($condition, [
w" {' x# f3 E4 @- a9 A: [& X/ ] - 'skip' => 5,
( [# q9 z4 O- J4 g; | - 'limit' => 5,
9 \6 }) G0 v, ?9 {: T7 ]& k! Z/ R - 'sort' => [
s5 s2 z" f- [- X3 { - 'time' => -1& }& v4 S) P/ S$ G9 P V u
- ],//排序' j* r& i+ P6 X+ D! p) e
- 'projection' => [
5 j. r2 N' U8 H' o' q8 H4 k6 r- a - 'name' => 1//指定字段5 ?: r4 }: E9 b) _( J# @
- ]
+ w# T8 f, v$ b# k( {0 r - ]);
复制代码 5.删除- $collention->remove($condition, [$ H2 u u) T$ _7 u
- 'justOne' => false//删单条7 n: J. V+ p) U
- ]);0 B; L! Q0 i7 Y, |* y
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);/ k% G9 d2 ]$ b( X3 Q# ~
- $collention->deleteMany($condition, $options);- q3 D- H! p8 R7 q; C$ [
* w% X2 j) ]1 B% M" y- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([! x$ D J2 d6 Y2 C4 |
- '_id' => $tableName//我在自增表中用其它的表名作主键
' a$ f& U$ u- h7 @, K! n - ], [
: T2 |1 S1 \0 J- y/ x7 Z - '$inc' => ['id' => 1]//自增
; h: [/ ?' F5 y6 ? - ], [
& {$ v9 ?) e6 {/ K+ Q9 o) R* A - '_id' => 0# z5 ~- p, P5 d. V7 R6 U# u. i0 g! s: k
- ], [$ k7 {/ P( @* L# g0 j
- 'new' => 1//返回修改后的结果,默认是修改前的% |2 n; n z; u1 {8 _6 C: d* S
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([/ a- u5 I. i" u3 I# D# N3 k
- '_id' => $tableName
+ m' w. C; X2 ^& D V; }/ \ - ], [
0 E' t# P' i0 }9 V# z - '$inc' => ['id' => 1]
" V! F1 }; `8 _ - ], [' E! ]# ~7 J: A8 f7 ^
- 'projection' => ['id' => 1],9 {% T0 W5 W# ?& q; t4 q
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
2 Z* L! D5 ]1 ~4 E - ]);
复制代码
( a6 a5 h. _! U4 G4 `" U& o- j
! A( p: v, I# |( T% s. f |