|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
" x5 r/ k$ y$ u( N! A" N$ F
" K* N: V: k0 a2 E) A- use MongoDB\Driver\Manager; Z$ ]( D+ o7 ~; e% L/ u, x9 a" |
- use MongoDB\Driver\BulkWrite;; f' `1 d. a" [
- use MongoDB\Driver\WriteConcern;
$ X+ P/ z, z2 r2 n, F- O7 A# }, J - use MongoDB\Driver\Query;
& [: r: O! G# n* u" d) y: s$ E - use MongoDB\Driver\Command;
+ e9 M- {: K% l$ |/ O
$ M8 K' i; c7 x8 x" t% i; H- class MongoDb {
4 A% N6 P. C: V$ ^8 M1 D, K) j - L4 \8 b* M( i
- protected $mongodb;
! b3 w+ Y Q0 U4 ^, x, z - protected $database;
) n4 B, C: y/ b; `0 J( D v4 ` - protected $collection;
* G+ Z& G7 ^* \: A$ w - protected $bulk;
( E; i; F' p. a7 E6 _; e7 D2 | - protected $writeConcern; a* M+ ]% A) k0 q0 Z+ \+ g
- protected $defaultConfig
- w4 `9 h/ e# i$ [' Y7 z - = [6 k2 @: c3 U+ M) B( {$ X! }
- 'hostname' => 'localhost',; ~5 b8 q3 @6 y f6 G A5 }
- 'port' => '27017',6 d. a: n7 L1 h4 f* Q
- 'username' => '',6 c' Q0 a4 _2 I4 }: j
- 'password' => '',2 ]: H; d1 b. H C3 ]. C
- 'database' => 'test'
|8 L. i3 N" x1 l3 P - ];
! ]2 E8 B) j4 R, o
! k3 K1 {+ v3 H) p- public function __construct($config) {( m/ b7 \3 }3 y: `8 R( b
- $config = array_merge($this->defaultConfig, $config);
- D, Q; }" K: C9 k0 h4 P - $mongoServer = "mongodb://";
7 o7 \ B: D+ y: Z7 a7 R) X - if ($config['username']) {
7 {8 Q3 X8 z% V3 w/ h# g( A - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';+ w0 _: X9 a8 Z) b* O& O
- }
4 w r2 {( i$ d2 V! }9 j - $mongoServer .= $config['hostname'];$ h# `5 S2 y: k8 n+ ~' E
- if ($config['port']) {
0 H0 E0 b; t: B8 [6 H2 U: f - $mongoServer .= ':' . $config['port'];7 ^1 S( c) r& z$ C! y9 m4 g
- }
- U3 V" q3 s1 S! }7 \ - $mongoServer .= '/' . $config['database'];
/ @4 r' |2 o2 C7 t# o3 v2 s3 j9 I
$ Z, z3 N( [6 }# F+ Q- $this->mongodb = new Manager($mongoServer);
[0 t8 `( s. r" r - $this->database = $config['database'];3 V6 @! Q3 r Z0 }" U: u
- $this->collection = $config['collection'];
# H3 \) R) ?% f- s5 ~9 D! _ - $this->bulk = new BulkWrite();7 W q$ P6 ^, Q0 A- |
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);% C- i9 t# E' i- m0 l1 q" `# a
- }
! z. \6 Z# v& m, m' Z - " c8 g* b6 k8 [
- public function query($where = [], $option = []) {3 k6 g1 C( r: G" {$ }& b
- $query = new Query($where, $option);
- e7 B5 F: Q9 L' U4 \4 g - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
8 q- p9 A6 i- U# [2 k; E - 0 L2 E; K- @& F1 l
- return json_encode($result);' w' y) [3 Y+ O3 F V; z
- }
5 @2 `' J# ]+ p( p - v v2 V+ u4 Z$ c6 c
- public function count($where = []) {' a& S U4 j7 ~: G3 `
- $command = new Command(['count' => $this->collection, 'query' => $where]);
3 y# W% d5 z7 a ]. n7 ~4 x( ? - $result = $this->mongodb->executeCommand($this->database, $command);
! k1 c& k7 {2 \5 @) B - $res = $result->toArray();0 U2 m1 J# }) E
- $count = 0;
. w2 `* J* o; }* I9 e9 j - if ($res) {6 A3 C9 P Y; \% {; _5 p
- $count = $res[0]->n;
& c4 q; k# s/ D& _- D - }( r) f9 W8 A6 _# N6 ^) K
! K4 B6 I& ?3 f$ ]( s# f- return $count;
2 Z' }+ U4 d" t4 q) f+ |0 p& Y - }
6 B" P9 k+ `, H0 R/ S' C: N - 8 Y# `5 p- J! i3 G' X- R
- public function update($where = [], $update = [], $upsert = false) {7 H6 f6 Q/ N u! q! m. ~
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);9 N7 o' L) y# S6 I$ ]6 \
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);) ^- T. f$ G( \ K+ c
3 X8 S2 Y' j( U4 D1 |- return $result->getModifiedCount();
; ]: k; d- I7 X7 n0 E - }) g) }6 p; U {7 y- q& j
# g; f0 z6 C" `: T- public function insert($data = []) {, R+ f# R' c# k; S; M' g. e( P# A) ?
- $this->bulk->insert($data);% U) b+ j2 r) [/ _0 W2 i
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
5 ?. R5 K- J5 P/ o V& G( q% C1 A
( c0 `' A7 B& {$ B. ]- D- return $result->getInsertedCount();# Q7 I5 }/ v) I* r% i; a" L4 J
- }, F* ~- P K/ Y
- O2 J1 ~3 y/ @* n# X* z0 x- public function delete($where = [], $limit = 1) {4 u* ^8 x4 y4 m8 L
- $this->bulk->delete($where, ['limit' => $limit]);
" H, S/ L. W+ O# t - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' k' o- }) h8 y: d5 C
9 O" d7 P! l- L- return $result->getDeletedCount();9 j; A8 t7 l/ G+ ~
- }
: a) ?" H; D, W- {2 a6 G3 ~! O - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新% I0 f$ _- h' g0 ]8 [3 R3 Z: t
2.新增- $collention->insert($array, $options);
复制代码- 新
1 m' {0 D! `, ]/ l/ n/ ?
- $resultOne = $collention->insertOne($array, $options);//单
, l1 p C! K+ n6 V6 [ - $lastId = $resultOne->getInsertedId();
$ ~ |, C+ T5 G _8 j6 e1 a$ T- ]3 L - $resultMany = $collention->insertMany($array, $options);//多( {- x+ o7 W. q9 T) C
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原1 k7 |( S" Z5 ?! P" _/ o
- $collention->update($condition, [
3 E: b& |( |: P' u - '$set' => $values
( a; I! ~ t& d8 i - ,[
( b4 I { C& p - 'multiple' => true//多条,单条false
6 c9 E @2 M6 B% Q/ F; r' n - ]);
复制代码- 新
' P" v; c0 X, B9 Q5 g6 V
- $collection->updateOne(
, x. C0 \1 k1 G: I. o - ['state' => 'ny'],
: C6 Y1 r) _. F0 y8 e% r - ['$set' => ['country' => 'us']]
k3 O: U4 h0 i - );& E9 ?$ z" k4 }5 s& G- @& T. V! c
- $updateResult = $collection->updateMany( {6 J4 Z* ` M: Q; y5 E5 s" V
- ['state' => 'ny'],; S3 V) v) _$ @
- ['$set' => ['country' => 'us']]
N( B( B. t+ o0 @& a$ U - );
6 Y# b/ y, C& d/ t* I3 z - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [, Y: K2 V! w ^# a+ F7 K
- 'name' => true//指定字段
# Y% C8 Y' Z+ u: R5 C - ]);
1 K( ?- \, w: d, k0 f$ I3 U, i - $cursor->skip(5);# U* X2 C, j4 G
- $cursor->limit(5);0 d) Y5 I' Y8 }. A: l6 p7 ?9 q
- $cursor->sort([- e& w0 F& h3 l3 [$ g5 Z- e! m1 u
- 'time' => -1 a/ N- ?6 g @, j i
- ]);
复制代码- 新; [* B. i/ V' S9 J% \" _
- $cursor = $collection->find($condition, [+ f* O; v* G3 G( }8 Q
- 'skip' => 5,
- a8 i$ S {" f4 C1 H+ [ - 'limit' => 5,
~1 p L$ c& Z, } S - 'sort' => [
" H$ Y+ I) u2 T9 O0 h - 'time' => -1. W! }9 @! l3 M8 _! C
- ],//排序% D3 C" o& X; L2 v* i
- 'projection' => [* e0 Y9 C( e9 {& |) |$ e1 p4 M3 Y$ ^
- 'name' => 1//指定字段
4 J, v3 c+ A( J3 N! d; ] - ]
3 j; Q# X- j6 L) b% l' q - ]);
复制代码 5.删除- $collention->remove($condition, [; i& Q, v" h3 ?$ V' A
- 'justOne' => false//删单条4 B& U, z: S4 o( _
- ]);5 @* ?, m% _1 F* Q' E5 M
- $collention->remove([]);//删所有
复制代码- 新) T3 Q0 m% {6 |* a( o. c
- $result = $collention->deleteOne($condition, $options);
, U5 P j% {/ o+ z+ d; V+ @0 H - $collention->deleteMany($condition, $options);
6 `) ^5 F( x5 f. ]9 L
5 a, Q; [+ p4 A+ H f6 v- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
! H9 A5 E2 r0 F& M - '_id' => $tableName//我在自增表中用其它的表名作主键
) {; e6 J3 k6 @" V - ], [6 I9 q5 J/ J3 \% H( ~ M6 l# V
- '$inc' => ['id' => 1]//自增5 }' e& ~- [" }2 G* Y
- ], [
% `# H8 N7 r. S5 K3 p - '_id' => 0
1 k9 K: T7 ^% v7 j* F R" x* N5 Z, D- w, b - ], [- }3 l- A9 q" w3 a- \
- 'new' => 1//返回修改后的结果,默认是修改前的9 z5 t( V% L7 I
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
' U- B8 M1 j5 y - '_id' => $tableName
* U3 Q& l" @+ J% j$ f; n" T* @/ G( j - ], [" O6 @( }! e" u- L* ~
- '$inc' => ['id' => 1]
/ T" f2 e$ V% S" d# { y k7 ] - ], [! ~7 |7 q4 i5 w$ q9 [* ]
- 'projection' => ['id' => 1],* k; m( d7 O# d! V
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER7 Z) b, b7 |, D& z: U
- ]);
复制代码 " Z( f. u% R; E1 n
$ W2 t, |4 S0 ]4 W# K
|