|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
b C. {* K+ l- p6 B3 f - 2 S2 l) q+ W/ n2 P5 V0 _, @4 t" s
- use MongoDB\Driver\Manager;4 M# m9 `' |, W0 x+ e
- use MongoDB\Driver\BulkWrite;
# e6 M/ J0 S' b1 m1 c; x - use MongoDB\Driver\WriteConcern;
7 O2 q. `! e7 \+ A; K" ? B6 R - use MongoDB\Driver\Query;
8 j+ Q& P& u4 R" y6 ? - use MongoDB\Driver\Command;* y5 j5 W% p. i+ A
- 6 `( x' M; t F
- class MongoDb {
9 {2 T8 f) n: w1 a' y - 9 d, \; }9 K: |7 q: Y9 l
- protected $mongodb;7 U5 o# x2 C+ K% c& T/ z
- protected $database;
" ^* P+ e% l5 h' Q+ l( f - protected $collection;
/ ~' [ ]% Q7 n9 B8 D. U5 _( ~. n - protected $bulk;! J. p/ c3 k) Z- K( a/ \
- protected $writeConcern;
7 L- n( D5 b+ o2 |) L - protected $defaultConfig
7 J' O3 T) ?; Z$ E8 H5 p$ T$ U' s - = [
1 T& ^+ E! ^6 X& n" m' i - 'hostname' => 'localhost',
- E0 w5 {. G! i/ Y. J - 'port' => '27017',3 X3 Z$ r* R# P p% p
- 'username' => '',5 {& S) b" c! f/ D4 [7 [/ H
- 'password' => '',6 F' B* u1 l% t
- 'database' => 'test'
8 P0 z+ d1 q3 }( q) a3 B1 p9 @ - ];
$ B. R5 Y: r" ~2 r* I& N- ^. u! T - . Q# E2 e. j* F, \' t1 J
- public function __construct($config) {
C6 W& A1 r4 C# S: @ - $config = array_merge($this->defaultConfig, $config);
7 k* n6 N7 z3 L* U' C8 A - $mongoServer = "mongodb://";8 d, }( H# W$ I
- if ($config['username']) {& ?+ V! k1 c! l+ a s) k
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';0 U, V4 E) a( o$ ^3 }, D1 Z
- }8 J9 C& Y/ N9 ~& }6 \' K8 F
- $mongoServer .= $config['hostname'];; ^& e* t* |2 C) h( f/ o; Z" l0 M
- if ($config['port']) {! S3 |+ `6 O* I; S, J, J
- $mongoServer .= ':' . $config['port'];6 a% Z/ _2 Q: P& `
- }
/ }) v# K! A* ]! H! v - $mongoServer .= '/' . $config['database'];7 r% z" U0 }- O- O+ _) c
- * n3 l! C; L" U1 ~* W
- $this->mongodb = new Manager($mongoServer);& ^) w1 k& Z7 s3 [7 y) |
- $this->database = $config['database'];
% e/ Y9 g0 Q5 u* G. _' N - $this->collection = $config['collection'];
. c0 ` A9 ^3 P$ x6 S; E$ p# C" G, l - $this->bulk = new BulkWrite(); a+ D6 l8 E7 a* l6 N% W
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
% ^# c7 H) `4 z$ s0 \( o - }9 L3 i. M$ _( E2 K
- e& p, y. ^; D- public function query($where = [], $option = []) {1 V( V: m) @) g$ o# X3 D
- $query = new Query($where, $option);
6 A$ Z' t7 V( H x- a& A# e" v; i% a, k - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);; I8 i$ N$ p, d6 D. n" j. v- c
- : G* `; l7 d4 Y$ x" S$ s# f8 s
- return json_encode($result);
* b+ t( a4 R/ e& i: P% G/ f - }1 |- o0 r+ X1 T3 o# C# I v7 z- C2 K. }
- & A2 a3 x D, g
- public function count($where = []) {
% q$ J, C* C3 |8 M - $command = new Command(['count' => $this->collection, 'query' => $where]);
0 D( {* E2 l0 j0 ]" q8 J - $result = $this->mongodb->executeCommand($this->database, $command);
6 Z/ E, x0 E& X) D - $res = $result->toArray();
, ~9 a: a9 [- q2 I2 v2 q - $count = 0;, E+ J" d9 S; x8 N) J
- if ($res) {% D. u% K* w. h8 R* t; P' b
- $count = $res[0]->n;
" h+ h) L7 { {1 X' m0 e& u- B - }% g/ u/ K* S2 L
$ K( Y( F+ k7 E s9 Z0 P- return $count;5 ^- Z- F+ M$ s8 D. `
- }$ d5 R2 D) \! u. ]. v% H
- ' Q9 m+ ^/ f" ^3 X+ N7 g
- public function update($where = [], $update = [], $upsert = false) {+ _5 e& o, e3 i; H7 C# s
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);1 g. i; Z: v! H
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);) v7 M n, N! Z1 I# l
- 0 C# {0 |% s. t0 `; _! k
- return $result->getModifiedCount();
: Y& V% }) V' j# V - }
$ f7 C+ X9 z" n! T - / F. _& ]) ^6 ^8 U: h$ o
- public function insert($data = []) {4 y4 N$ x- {. r( U
- $this->bulk->insert($data);
) u! D7 R) P' g( F( ]. w - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);" `. v5 r# S+ s
- 0 `. t% S! i/ y3 r! G% I' ?: V
- return $result->getInsertedCount();/ o8 c w- S. `/ Q+ B
- }& P W; J) r7 Q' p8 |2 ~+ T8 ^3 Y. d
6 _( K: F$ @) i- public function delete($where = [], $limit = 1) {/ W4 D3 t3 _6 K9 g" @
- $this->bulk->delete($where, ['limit' => $limit]);
+ C7 T# G5 @- L6 ~3 H; b+ F - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! l& ^+ C7 K+ o, J
- 7 [" Y( U0 P# A5 m+ e4 X
- return $result->getDeletedCount();/ o$ Z( g O$ r g
- }
/ e& [) \0 h; s: n) K1 { - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原+ H" v9 g7 M' @! {. T( @
- 新- K/ }8 z/ `5 `7 I! [ n! q* Y1 z
2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单) _" D5 s0 q |1 K: G
- $lastId = $resultOne->getInsertedId(); A& `! l& f1 o& U- h1 G
- $resultMany = $collention->insertMany($array, $options);//多+ v- u3 Q- @: M }% T
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原) v" j. D" i1 A& }: ~" U, H( r
- $collention->update($condition, [
- ^/ E+ C# B s3 w2 E% I1 j0 m6 | - '$set' => $values
0 o1 Q0 ?. i y9 c! Q6 M) c - ,[
5 Q! K- P( g5 N- D* j0 f) p2 e - 'multiple' => true//多条,单条false
: X3 [1 u" i- R$ @4 g' K - ]);
复制代码- 新- ^9 {6 [: H0 Y' r$ q) x- M
- $collection->updateOne(/ D* s: C% R- x! G9 l) A$ {
- ['state' => 'ny'],
* h# I) \3 [- R, D# T( r - ['$set' => ['country' => 'us']]
/ D2 V# g" l1 c! ^ - );
) F4 P% _4 L8 w) \/ I - $updateResult = $collection->updateMany(
8 Z3 x/ `# i8 f9 f2 a2 X) Y4 Q - ['state' => 'ny'],, O2 C/ g3 M2 {8 \9 P/ i7 {1 ~3 l, D
- ['$set' => ['country' => 'us']]
+ e3 a% v* B/ q" | - );* F) P1 T6 |& }4 ?+ Z$ u
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [% T' ?1 w" }8 y( x' {- a l5 ]' H
- 'name' => true//指定字段: U S/ C% }; I' b& T
- ]);
) U' n& a) B% D' |) V; z; o8 }7 \, C - $cursor->skip(5);
' F" I0 A# U6 o5 N% J) O% s: N - $cursor->limit(5);$ m8 {! A6 i) L* \/ {
- $cursor->sort([6 f6 x( S q. e6 c
- 'time' => -1" \ R3 ~6 l1 {- @& T- s
- ]);
复制代码- 新$ T+ g+ \- c w8 r! U) V1 e& W
- $cursor = $collection->find($condition, [
' r% M. I. J0 h - 'skip' => 5,
. E; N; T3 k* k c1 j' b, M - 'limit' => 5,8 |. \# z7 i' P7 z6 u
- 'sort' => [
0 G5 t8 E3 ^5 z6 | - 'time' => -1
; ]& W8 ~) B7 A$ M( J. Z& \ - ],//排序
l- L1 N* q T; u/ [ @9 R9 q - 'projection' => [
, j* j7 v. i9 w: [ - 'name' => 1//指定字段( F; [( A1 F/ ]2 I$ y, ^
- ]8 M9 ? d; t2 G: |$ ~
- ]);
复制代码 5.删除- $collention->remove($condition, [
+ a, z# j M K8 O/ V; M! q - 'justOne' => false//删单条
& U- n0 o8 w( k8 z) u: `2 ` - ]);) M1 C7 f" l3 x8 j7 p# K- E
- $collention->remove([]);//删所有
复制代码- 新
( W# l2 B# ], k+ \/ @5 F6 I: ?
- $result = $collention->deleteOne($condition, $options);
3 H( j- i5 h3 p) P- g0 z+ g - $collention->deleteMany($condition, $options);
7 q) |/ S, \; q& t! l3 a - ' M$ x/ x. D# [4 {' [+ q7 u
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
4 |9 A' T% G* G - '_id' => $tableName//我在自增表中用其它的表名作主键
2 b( ]7 `9 e I/ b - ], [3 f: o9 \3 y" X9 k
- '$inc' => ['id' => 1]//自增) r; F, ^# j3 V5 x6 L! N) h
- ], [0 }4 n% z/ |! x1 F2 @" i8 B% V
- '_id' => 0
5 G) k0 q1 M/ M! U, h1 ?+ | - ], [2 U7 |! g2 _% D, ^( o) s
- 'new' => 1//返回修改后的结果,默认是修改前的
- @, S9 p) |+ g4 n - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
9 }1 }% ~- D* \. r7 o. s - '_id' => $tableName
& E. V& S; i+ U2 \ - ], [
" q; J; J) i' F4 t+ P( k) H - '$inc' => ['id' => 1]$ x5 Y- g4 r+ s( H
- ], [
1 j$ O9 t( Z/ j) x U - 'projection' => ['id' => 1],$ E3 `$ {' p2 d, O- }, W
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
4 Z( \" I0 Q0 P2 R d, G) I - ]);
复制代码 4 ?+ B" V4 ~! _3 M
, W3 I( f# P) M) s9 @9 D |