使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
5 [+ }6 Q S; U1 N6 |2 u9 y
9 O# H) z% P. T7 ^3 n! h. J- use MongoDB\Driver\Manager;
9 s4 n# ?- }. D - use MongoDB\Driver\BulkWrite;1 q$ ~3 d' |' x8 ^3 ~
- use MongoDB\Driver\WriteConcern;- [; {" b% d7 t8 s# W
- use MongoDB\Driver\Query;
. e" A& Z0 y( Q. J4 ~& s, a2 |8 a D - use MongoDB\Driver\Command; k. {- l6 ~( o" C7 ~4 e6 S
9 S2 h) I7 J5 _ z1 K( y- class MongoDb {
) ?3 |( \" m5 m. a$ [ - " g! m( _( O: M U& R0 w2 _5 y
- protected $mongodb;
- l% ^7 h7 E: g) M. m5 x6 \ - protected $database;+ t6 n! ?4 m6 u5 `" w0 {
- protected $collection;# U/ W$ g, A/ R# K
- protected $bulk; m2 d3 K( Z. R
- protected $writeConcern;! v6 w, ^0 F* t. Y$ c1 B( K
- protected $defaultConfig7 m2 n1 k. f* v ~5 E6 G
- = [. s; S3 F- u$ `1 Z% K
- 'hostname' => 'localhost',
1 ]) @' D* }4 p/ Q8 A- q - 'port' => '27017',
( K7 K; ~) }5 S4 [5 Z" b, ~/ q - 'username' => '',
0 }$ u' C0 ?! u2 O8 E6 H% g0 X - 'password' => '',
0 C$ {+ ?5 e# V S& h - 'database' => 'test'7 h4 \6 ~8 v2 J; A
- ];, D& Y$ c& V- l5 C& Y+ ^& v- J
3 ^4 Y. L+ v( m' P# O$ L0 v& u- public function __construct($config) {
2 L0 c; V# J/ g& R4 ]" M0 [. P3 k* c - $config = array_merge($this->defaultConfig, $config);2 ^+ i# ~8 t. b! P5 I" D2 e1 N t
- $mongoServer = "mongodb://";
8 ~$ H; F1 a4 h. P: ^/ k j - if ($config['username']) {
7 O9 `8 ]5 i V: O" w - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';5 G- v' T/ ]& |) E6 p5 C) b2 A
- }- Z- T3 J6 s+ R1 S& s
- $mongoServer .= $config['hostname'];% t& z# E& g" \; Y# Q
- if ($config['port']) {, I9 |3 p0 P4 @' T+ Y* ]+ h. h- [
- $mongoServer .= ':' . $config['port'];5 I+ f- c' j" L' S- v: h% U
- }6 [" x+ n1 E5 ]4 [0 _/ U4 s" w: H
- $mongoServer .= '/' . $config['database'];7 X/ ?/ Q6 @' m. Q n: ]
- * y) }" Y7 A2 m9 [0 g
- $this->mongodb = new Manager($mongoServer);
5 L9 F5 _' i, a. n% d6 t) c: d% z - $this->database = $config['database'];
5 G; q2 L, i) l, N6 h8 S4 U - $this->collection = $config['collection'];4 v* y; ]$ R+ E# r# R
- $this->bulk = new BulkWrite();
+ ~9 k% m5 c9 s - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
M, |. q6 o# F" ` r8 _ - }& Y# p: {9 m2 u& z' g
( b7 C0 S, x9 Q6 f0 w- public function query($where = [], $option = []) {
7 ?/ I% ~6 a8 e" @: S/ U - $query = new Query($where, $option);
. Y% b$ E" P/ V) _: R0 S j d - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);! e: ^4 u4 ^1 C
- $ |# `+ j# Q' z: U8 ?
- return json_encode($result);# C. a9 b" S# ]% R* v
- }" D8 H, L) Y8 U: I) ^0 ?
- ' @0 u8 D8 k* }7 @* e
- public function count($where = []) { H; Z; g+ D. y$ I% R* _9 V
- $command = new Command(['count' => $this->collection, 'query' => $where]);
+ x; J8 w7 Y8 L$ H3 i2 ` - $result = $this->mongodb->executeCommand($this->database, $command);" d9 m" y& Z* \0 i8 p- k0 A- ~; ^
- $res = $result->toArray();2 n* w; p, Y* u2 C0 X
- $count = 0;
( u4 O2 J5 j. h7 r0 Y - if ($res) {, \$ X& |& K. V; W6 N& C) T; q
- $count = $res[0]->n;
b* m, B2 B* f7 ?; E, p. K. m. m - }3 | d5 C/ p0 ^5 l9 w+ Y
- , V: a7 ^- M' N7 x3 Q; K9 |- M
- return $count;
6 x7 ^/ [' B7 Y8 o$ t, }9 u/ X5 _: d - }0 ]: S# \" D: A! X/ x
6 b- z2 q- a2 D7 N; P* a- public function update($where = [], $update = [], $upsert = false) {
; X @6 {7 _: H: I7 v- H# _ - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);$ o# ]: v% @9 _; D. h3 z% V5 j& W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);* O. d8 ]8 v# [ Z
- r5 x7 O, ?/ p" [6 R- return $result->getModifiedCount();
1 `% `' c9 d/ f g: F- L! | - }4 i3 s. z8 D% b6 x- t
- ) n0 x3 {7 E; P& Z
- public function insert($data = []) {8 O3 x0 t& L# z" A9 g( B$ O
- $this->bulk->insert($data);
1 V+ J: s! D+ z9 W! z - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
! I$ J* f0 a) j1 r' c7 X - ( q( u0 I5 i7 ]3 R1 [6 S
- return $result->getInsertedCount();- ^ P4 |+ ]) L) h2 z
- }
3 F6 ?$ _, x& V1 ]* S* I - : ?5 d R- {1 a* y7 ~3 h! o
- public function delete($where = [], $limit = 1) {; |3 ^( T& c: T' G% }
- $this->bulk->delete($where, ['limit' => $limit]);) C9 Y4 V- Z- ~* R) `. [2 c5 ], c
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! d M' C" ^8 W; a% u' K2 b
) m3 o- P5 g7 |! K$ f8 B. \7 m- return $result->getDeletedCount();6 f7 M# z! Y x, i; N$ s
- }
/ x0 X; @8 s: V6 \! U8 j7 |/ e - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原- y9 c) c; P A; u9 i' B0 Z
- 新* \/ l3 D9 v! C: p; J+ U8 [
2.新增- $collention->insert($array, $options);
复制代码- 新
' q0 |! R: E0 h [" d7 m
- $resultOne = $collention->insertOne($array, $options);//单
& ~' v( Y! P% {; S9 v/ w2 S% Z - $lastId = $resultOne->getInsertedId();5 N; E" E/ Z7 t6 l
- $resultMany = $collention->insertMany($array, $options);//多! m% E# ?6 k; z5 K$ d
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [3 N" x( M) [+ V6 w
- '$set' => $values
/ y4 k7 Z1 m6 D% K# v8 P& v - ,[
1 o& u( F% Z3 R; ]! p- K - 'multiple' => true//多条,单条false
, Y; Y0 a0 X% o9 \3 V: r8 N# [: @ - ]);
复制代码- $collection->updateOne(
0 P3 P$ y. H! D/ b0 H0 d5 [/ M - ['state' => 'ny'],
) d3 t$ q+ @. ]3 e - ['$set' => ['country' => 'us']]
. N; J; b6 d- m e0 `/ t - );
$ U# `4 g& p2 Y x - $updateResult = $collection->updateMany(4 c5 T7 V5 U* C9 ]. ?
- ['state' => 'ny'],
+ {2 q4 c4 u j4 h0 r+ @1 h - ['$set' => ['country' => 'us']]
% H& R" r1 k! U" t5 j7 F: M S - );- z' M# t. Y4 g
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
: k0 O* s; F4 m$ E3 Z1 t; H
- $cursor = $collection->find($condition, [
5 ]1 M$ V7 E7 W4 f, z( s$ z - 'name' => true//指定字段
) }4 Q; R5 Q8 g+ n4 {9 ? - ]);# z/ ]' Y( s; j0 Q
- $cursor->skip(5); B6 v$ V& G$ t5 c% v- L
- $cursor->limit(5);
% l- z6 [5 J I# y% f3 `7 I1 A6 J' [ - $cursor->sort([$ ?: {3 O5 i2 s9 W1 }! q
- 'time' => -10 B0 @, e" y- [& {
- ]);
复制代码- 新
& [0 L8 [4 \2 q# K* g" h% P
- $cursor = $collection->find($condition, [4 [& t, m v- o; l$ t# Y( h
- 'skip' => 5,
5 U6 Y5 Q( e$ Y - 'limit' => 5,
, `1 L2 ]5 M0 V1 o5 _+ \/ X - 'sort' => [' D; a6 F+ y5 Y9 V! S T$ a- S
- 'time' => -1
7 `+ f! I! g( n5 l) l. X - ],//排序. G5 v$ J9 D+ r1 ~
- 'projection' => [; s+ I7 _( P3 |. Q
- 'name' => 1//指定字段
1 ?2 p% M8 D: Q- Z, C. J& E" k - ]
; ]8 s7 i* D: c: e2 O( ~2 `( L - ]);
复制代码 5.删除- $collention->remove($condition, [, Q7 N4 l4 R, g4 v+ M W
- 'justOne' => false//删单条
- P! p# W; H& R+ q% t( S Q0 H" n9 g8 ? - ]);/ k+ t! e! N0 P$ F) x
- $collention->remove([]);//删所有
复制代码- 新( E& V7 Y( m7 M; }9 ?* H. k
- $result = $collention->deleteOne($condition, $options);- L% G& c; P9 f- G
- $collention->deleteMany($condition, $options);8 z8 T& D, ~& R, l, [
- + c F6 b( u9 y! _ h
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
B D, ~7 E- C7 p - '_id' => $tableName//我在自增表中用其它的表名作主键% g7 t! w" b I$ q7 _
- ], [
9 q! \& [; Y- q9 J/ F, T, M1 m - '$inc' => ['id' => 1]//自增
9 X& Q) d7 Z8 M3 q( d - ], [- |: n3 B4 P+ r& E
- '_id' => 0
! k7 u6 h2 |2 J/ N - ], [
, w/ C1 e j& J' s - 'new' => 1//返回修改后的结果,默认是修改前的
$ v2 A9 Y6 d" a2 f4 r6 ? - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
" o$ v5 c+ Z6 Z4 l3 B5 z( o - '_id' => $tableName. z: |, A% w C$ v) Y1 X
- ], [
& h, P4 X/ T5 Q - '$inc' => ['id' => 1]1 _. J" ^5 @- v( p" @
- ], [
! [! P9 R$ G1 _8 q C5 s/ R1 p0 H - 'projection' => ['id' => 1],
8 X: o# {' @$ z7 A1 j9 s2 |* x - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
- h2 L* y7 U4 a: a! p8 ? - ]);
复制代码
7 d0 E1 V; Y) L5 X1 s6 w* \
3 O3 M! x; ], J# e |