|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
2 [; b/ I+ A/ I& H
1 x! b: x' O7 z, @; G/ K- use MongoDB\Driver\Manager;
! B* }+ W0 r) O c6 K - use MongoDB\Driver\BulkWrite;9 J( O( I, U8 x# V$ Z) b
- use MongoDB\Driver\WriteConcern;
5 h5 I$ G2 V! W - use MongoDB\Driver\Query;" Y7 Z7 b9 U! N( [4 Y% G- D
- use MongoDB\Driver\Command;1 `4 ]& `8 {) O6 c1 Y
- 8 G1 T5 a8 \/ G, a, p5 @6 }" ?
- class MongoDb {+ w* O2 j5 @7 W1 `
4 D) U) v/ O# Y. a, o1 l- protected $mongodb;
2 u( y+ v" q! B. b& N& h - protected $database;* P2 g# f+ t' X$ ~- u3 G* Q
- protected $collection;! j' o8 Z L' w: T
- protected $bulk;! p; o5 x* z- s& D! g0 M1 I
- protected $writeConcern;% d7 W3 a0 }, Y) x! a" C" W
- protected $defaultConfig# ]- Q$ C- P) M7 ~1 f5 m% u9 d) A
- = [4 h) S3 q: E) p5 c4 Q
- 'hostname' => 'localhost', u1 P' C* w7 u" c
- 'port' => '27017',
" O- [" M8 Z7 p+ K. f$ d8 v - 'username' => '',
. U, r& s2 |- {6 P7 r/ k - 'password' => '',
5 g3 D3 f, e. Y/ D - 'database' => 'test'
}% q- e5 X. P% _: T- I i9 W2 M - ];
# _6 G* u/ B, q - 0 x% G* E) O3 c E! E1 ?$ Q( i u
- public function __construct($config) {! q" p f8 G$ v8 W& i* k
- $config = array_merge($this->defaultConfig, $config);
) s! U3 J& ` ~" {* I - $mongoServer = "mongodb://";, _9 Y/ e \4 H' T" o; ?
- if ($config['username']) {
, P. A1 T) ~; l2 G& l: Z6 y, c( y% d - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';; {6 o7 ` g, R" ]
- }1 F( W2 p f0 I+ F- W& d) ~* Z% F9 J
- $mongoServer .= $config['hostname'];& h' k/ m7 Q8 I2 h/ _, U
- if ($config['port']) {
' r! ~+ G+ p* w; n3 M - $mongoServer .= ':' . $config['port'];% j& R8 v1 F2 m7 g* }7 T' m
- }7 U1 ~" S5 m4 ?- p7 K* w- v. |
- $mongoServer .= '/' . $config['database'];
; i% W4 M3 `$ q+ d9 v
+ J0 I3 R/ Y* U8 c- ~. |- $this->mongodb = new Manager($mongoServer);
, u( v7 y8 ^ S$ _4 \' @! ] - $this->database = $config['database'];' p$ J) u" T' ^- A" H/ [
- $this->collection = $config['collection'];
8 M+ t9 i: T( M - $this->bulk = new BulkWrite();; F0 v5 s. @% T* K) I
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);' g8 A/ ^- [4 J- _1 g# F
- }
/ t4 i& E* `4 M/ e. }
, |" J. ?4 N% l% d$ d- public function query($where = [], $option = []) {
' o' ?# p8 j( U$ [* C - $query = new Query($where, $option);
! u% Z1 @, u. V1 P! @ - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
) [) V2 O. Z# f1 ^
* X9 R9 K. E% D1 I! k) q- return json_encode($result);+ F H" |( }3 ~' ]
- }- U' n" R5 X' K' @/ U+ I9 d
$ p. \. e, Y3 g2 F. s" r4 ]- public function count($where = []) {
* t7 ^; p. G& R4 ~ - $command = new Command(['count' => $this->collection, 'query' => $where]);9 m9 f/ L& }, \7 d! R. l
- $result = $this->mongodb->executeCommand($this->database, $command);
$ n D* }' T# { - $res = $result->toArray();
' x6 K- U4 h0 ] - $count = 0;
! X4 z, ?+ B! ?0 Q5 D% @$ d$ w* ~0 F - if ($res) {! l. m, i: q- I' C) h& ~6 A" f
- $count = $res[0]->n;
" W6 y! H9 Y' f, w! r+ Q9 g - }
/ w) m$ X3 K8 J6 D0 P( i - / j/ g/ b* ^* x$ v9 J
- return $count; c* q. S0 N+ |: r8 k% w$ j
- }& M+ v; l6 @9 m$ G; g' Y0 w! b
0 L* |1 a& \! m4 [8 S# ], r; b) q! i- public function update($where = [], $update = [], $upsert = false) {, Z( e/ U" `8 y7 o
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
8 B; X! d$ i' v% Y9 P2 X" a" R/ J - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
5 B7 ]) Q5 q& Z+ ]
8 _7 Z- D6 O7 c8 j6 P5 @1 F8 M- return $result->getModifiedCount();
2 c3 s; y% b8 E8 h/ R. X" ? - }
; T& d- M6 W- h7 }$ b g
m" \7 h4 `8 s9 t) c- public function insert($data = []) {% K+ L0 n- J0 @
- $this->bulk->insert($data);
. c& m. p. q0 _! ? }( x, ? - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
' d' Y& n! ?: H1 U! F1 C8 J; M! J. F - & w J; U9 o3 g$ C$ q" _ i. K! d
- return $result->getInsertedCount();5 [1 G+ W& C2 N1 f0 @- k7 J- a
- }
x8 I m! p f' h9 k - ! `1 ^$ l; Z% U% D1 l
- public function delete($where = [], $limit = 1) {
q* M7 J2 l# A% v: m8 p( [ - $this->bulk->delete($where, ['limit' => $limit]);
2 }' l* ?8 Q( v' } - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);! ]7 v) m; W+ u, f8 [( b4 {( e
, O) K1 q1 E# [5 g3 O% s1 X7 e- return $result->getDeletedCount();
" `: M7 w' F$ e* U0 w - }
* a- k, v- W5 S - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
1 j9 ^) j. r% i5 l& ~% Y
- 新6 r1 H2 D& U6 h' r+ D9 K8 O7 Y9 G
2.新增- 原
) d" Z2 R) u- o: `/ w1 i/ X/ c
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单, |! Y6 [4 m% f
- $lastId = $resultOne->getInsertedId();" T U* N8 U4 F2 t, q3 l5 K
- $resultMany = $collention->insertMany($array, $options);//多0 M" B; p$ p$ e4 S. u K7 q/ w
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [: m+ V5 N4 D+ t l8 m
- '$set' => $values
0 `5 O6 `) f' R3 g - ,[
& y7 I4 v# F3 T4 T) q) I - 'multiple' => true//多条,单条false
; r9 v6 T! p: `8 ~' W - ]);
复制代码- $collection->updateOne(
; F/ \6 x! {! C& c M - ['state' => 'ny'],5 ^7 w: s- ]& J% z2 [
- ['$set' => ['country' => 'us']]
+ ~! s+ A/ m! T* }2 h - );7 t/ U4 O+ q. l
- $updateResult = $collection->updateMany(
- h# E E _. n1 K - ['state' => 'ny'],
: N* R+ _" O5 x+ P - ['$set' => ['country' => 'us']]
, g/ H. @1 n- Q2 g) K K- u - );
6 H9 q' J! g- h - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
: g3 r1 J$ V. t F# H - 'name' => true//指定字段
$ m' _6 p. f! s/ h8 f, k" ^- p - ]);
" Z! h @7 ]! A% i# n5 ?; g - $cursor->skip(5);
4 Y; Y% h( S' _* L/ i2 a6 a3 { - $cursor->limit(5);
% l5 Q3 O! `2 a* f1 S - $cursor->sort([
/ u9 p0 u) Y0 Z) o# V1 d! Z - 'time' => -1( a3 X0 r4 D: m( p. K
- ]);
复制代码- 新" P: L! \! N; i% _- [- X
- $cursor = $collection->find($condition, [
1 h1 C. m5 o( `7 p7 B9 P' a/ y/ ` - 'skip' => 5,
o" g# `' A0 {: b4 o5 J, ]. y, `! Z - 'limit' => 5,
% U' i9 _/ g' [$ H - 'sort' => [
% x5 M1 y d- J9 {3 ^ C - 'time' => -1
- r: x j; O) c. q- A - ],//排序
. o! u9 I$ h: {9 \/ Z& `( q! x - 'projection' => [7 c# T( x; R8 f g/ u/ e
- 'name' => 1//指定字段
6 h _- b& _$ U4 Y9 Z. {7 w - ]
. f$ `$ u7 c) r# l) a - ]);
复制代码 5.删除- 原& B/ _2 Q5 r$ t! @; \( R( z/ h2 J. ~
- $collention->remove($condition, [
. ]' X0 n. f) u( H0 u4 g - 'justOne' => false//删单条
) `) B9 G& z+ p% z( B3 m - ]);
4 ]8 I, Q3 D1 s2 D) l; I1 x - $collention->remove([]);//删所有
复制代码- 新. _$ J7 M/ u7 }7 r! L4 N
- $result = $collention->deleteOne($condition, $options);
- S. z6 `: Y+ |- s6 a - $collention->deleteMany($condition, $options);+ i9 ~- s: n' v6 e
8 b0 Z0 I! O. i; D+ ~$ {" n1 I- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
5 L% H; }4 @# I8 L: T - '_id' => $tableName//我在自增表中用其它的表名作主键
$ t6 M9 a1 u4 d8 |- i - ], [; S! x! k- S1 p) s
- '$inc' => ['id' => 1]//自增
- W3 c% v7 [) h! g9 I. N( H - ], [
: L9 x; X3 O7 j! O - '_id' => 0' e, r' r+ Q t" X1 R2 k7 B# W6 C' e
- ], [
9 U8 ?0 f% m9 u' B% [2 J2 Y9 _: A - 'new' => 1//返回修改后的结果,默认是修改前的: S! H1 t8 _7 t$ G) S- v/ p7 [3 o
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([1 m. K( B3 S2 s- p; R( J9 b' e0 E. z
- '_id' => $tableName: P' B& N. ? d% c+ c7 z9 i0 e* _2 v
- ], [
- \8 z# G* X4 s; c. w& ?9 N& _ - '$inc' => ['id' => 1]" {% y. ]' m( L: h6 h
- ], [
0 L# O; |1 {5 z7 z3 J# I - 'projection' => ['id' => 1], |+ h- ~. J, B* R
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER, a L% w5 U; g4 `. C& _1 @6 J
- ]);
复制代码 & y4 {! v$ t0 f5 i0 L; @
' f( n+ [) l4 w/ @& l
|