|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php" [0 u! y0 f! H9 V( p4 f1 }
- * a" h' ]( S7 W4 f& t
- use MongoDB\Driver\Manager;& [( d6 e- J7 x& w5 Q3 b) B
- use MongoDB\Driver\BulkWrite;
' [$ X8 }' o p! P3 w' H$ ]7 J/ Z) T - use MongoDB\Driver\WriteConcern;/ z# Z- c* m! S8 M0 t2 ~
- use MongoDB\Driver\Query;
0 D( {- j7 P" b+ Q* A M - use MongoDB\Driver\Command;0 u0 {) _/ u: O, h1 h
7 j' [7 o n% R% C8 E' O- class MongoDb {; {* S7 b1 m! g* u5 ^2 g- Y
- - I; s# L3 i! T" j$ i7 h" C; K' T
- protected $mongodb;3 m5 C+ p& Y0 H3 x* ~1 F4 \
- protected $database;( c0 b5 J3 O) r
- protected $collection;
- L/ a n1 Q2 O& p - protected $bulk;7 h" G6 M3 D7 P
- protected $writeConcern;2 |, @8 B% o! { n2 U
- protected $defaultConfig8 F& c, F3 I- Q; a3 |' X4 P/ n3 k
- = [
7 a" E+ p5 q( ?# f! v - 'hostname' => 'localhost',* a+ p, \& V( u2 j! a
- 'port' => '27017',
- T1 C+ C' S) q0 _, b' N% ? - 'username' => '',
/ ~% u# o* U$ \+ m8 N" y% [ - 'password' => '',
. V5 X7 a1 J8 g - 'database' => 'test'( Q2 {: H) s2 Z. H
- ];
% v2 h' b1 Y9 W
" ?+ @% Y" j3 _+ t' T- public function __construct($config) {
' }. T- F. Q$ f" B, C - $config = array_merge($this->defaultConfig, $config);
6 y/ q2 Q$ q; Y, | - $mongoServer = "mongodb://";$ _" U9 U7 z/ A$ ]( O1 T* ]- m
- if ($config['username']) {. e) }) q# Q4 N/ a' ], A6 K
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
) ^7 s% K$ p# Z4 ~: t N - }; K( A! @ x6 C6 k0 f
- $mongoServer .= $config['hostname'];, b1 L# w/ S3 |2 d: w! S
- if ($config['port']) {
m; ~: P/ Z( G" g5 h$ N - $mongoServer .= ':' . $config['port'];
! N% e: x% J' M7 w3 K4 _ - }
" [, U4 \$ F8 a - $mongoServer .= '/' . $config['database'];
+ h$ K+ e. O( [0 T" z! s - 4 y5 q2 t0 @4 X- k$ ^/ z& m# N
- $this->mongodb = new Manager($mongoServer);: j9 }6 ^; a+ V$ b% @/ O% K# z
- $this->database = $config['database'];4 d; b- N: m% S, E2 o
- $this->collection = $config['collection'];
) ?" a8 d! i/ g1 |# _- W - $this->bulk = new BulkWrite();
' T7 Y+ M- o o - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
" A' Y+ q' d! v3 P; K! F/ W/ W - }" X; G/ d, w9 |% \ Q
- / N5 ?8 L" R9 g' a; O! \, A# l: j1 k
- public function query($where = [], $option = []) {8 F( n0 w& [! y5 Q5 q, J
- $query = new Query($where, $option);
- [: [. N7 B% r i& \; F* L) b9 a - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);7 m) X- L1 p1 b) N1 c
- 0 A; x/ a% q y) h& b
- return json_encode($result);( u* S) l- U! \: k
- }
+ c3 }( _) U. u# g3 B
( u. v, _2 c0 y2 k3 ?- public function count($where = []) {
! x7 i/ \2 }- s' w f - $command = new Command(['count' => $this->collection, 'query' => $where]);
0 x& F3 O# K2 ]+ }& k" m6 }4 N1 s$ k - $result = $this->mongodb->executeCommand($this->database, $command);
! T+ d, f; `4 [% x0 W' u8 C - $res = $result->toArray();
$ _) r/ s& @, G. b - $count = 0;
" Y" }( R0 z" L- ` - if ($res) {
" i8 T' r1 p) |8 R - $count = $res[0]->n;% D' h, r+ @1 n
- }1 ?& \$ s/ e- Z9 z. I
, y5 a* }$ N A7 h3 @( o- return $count;
( z9 ?8 ]4 `) a/ D1 T% j8 @ - }( }5 c: @, a* S" E* E
- ) y, `- c6 j1 o" C8 e9 } H" j
- public function update($where = [], $update = [], $upsert = false) {
. D8 ^& [, W% _4 I+ Z" w9 n - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);+ F. E; q% n1 n4 M/ U# x
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
8 q0 x* ^6 b+ l1 R
3 c- y# i; ~; ?7 k2 W& N" F- return $result->getModifiedCount();9 \, }3 g* k, \0 {' e/ N$ I0 `% y2 v
- }
+ F( `& r' Z4 d% a9 n3 b6 i- x$ w - & _% F3 ?! m* [0 p2 ^* i% e$ r
- public function insert($data = []) {% W* M/ [5 k: u! \0 g9 m
- $this->bulk->insert($data);. D( u8 h+ ]) @ F7 _
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);8 y: x# b" S4 N( p6 |
: n- G: q. l% W0 m: o- return $result->getInsertedCount(); v. b7 s# R! c) ^- U% m
- }" j9 ^* b2 _% L8 n0 M$ y
- 9 c) t1 L: A% ^. Y
- public function delete($where = [], $limit = 1) {; X# `1 d+ o: h" R+ C
- $this->bulk->delete($where, ['limit' => $limit]);9 J) q+ J7 C9 g" k% Q# V
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
7 p; N4 r, t, [1 K
* v. D! { B' S5 U/ g' a- return $result->getDeletedCount();
9 ~$ Y% S& }$ i8 ~; W* U) \ - }
3 L6 b E0 x+ m- y; i* K7 l - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
" \4 |: R7 i$ d - $lastId = $resultOne->getInsertedId();
% i* @ k$ p# [3 c6 f - $resultMany = $collention->insertMany($array, $options);//多% `8 n! J& {3 r0 O
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [! X2 x7 U/ g$ E3 N
- '$set' => $values
8 i n; k8 B0 b7 j/ K! [ - ,[
$ ^& `- h: G/ I8 R% p4 e: c# [ - 'multiple' => true//多条,单条false: p+ E) }6 X: G
- ]);
复制代码- 新( O+ Y$ F9 T. j: f/ K! G9 g
- $collection->updateOne(
8 g1 d6 w m& b+ N - ['state' => 'ny'],- [) T' z( D7 ~. s( t0 i+ Z
- ['$set' => ['country' => 'us']]
0 U& m m6 D) k7 |% v# R - );
4 s+ Y: \1 D" M+ l+ L& ~4 i* p4 B5 R - $updateResult = $collection->updateMany(* ?/ r) u0 V) Q. H v& g5 ]& M- i
- ['state' => 'ny']," g/ c/ f2 a& A: q3 h& q
- ['$set' => ['country' => 'us']]# ]1 o) p! \- U6 `4 y
- );
% y6 f" ^, B | - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [7 V6 L$ E! h0 h+ b/ S
- 'name' => true//指定字段5 |7 K# A K6 ?
- ]);
: I5 k' u, B# P5 o0 ]! D - $cursor->skip(5);
0 W. n4 [7 e( w+ h4 l - $cursor->limit(5);
; i4 S' `9 P! @) s( E& w - $cursor->sort([2 J. a8 i: u0 y$ L) Y
- 'time' => -1
j* V" P J B( p9 \5 F - ]);
复制代码- 新) L$ A/ U- P9 V8 @7 b7 E1 k8 `
- $cursor = $collection->find($condition, [
0 m/ t6 X/ b: R5 w% N) S! K - 'skip' => 5,
, t& @# I1 |9 m$ n( A3 d/ M - 'limit' => 5,: |# c: h( Q, {
- 'sort' => [* B6 A" p5 E( R$ w0 C; r/ Y
- 'time' => -1
& c: g H' s5 j5 K' N - ],//排序9 l# S. B# a* k5 @6 V$ ]. ?6 L
- 'projection' => [
2 r# ~7 |3 _& d: a* ~8 |, E; s - 'name' => 1//指定字段
; }& x" B- t+ F8 n - ]
2 ~! P- g! {8 h - ]);
复制代码 5.删除- $collention->remove($condition, [6 H9 S" U' |5 Y) G4 p
- 'justOne' => false//删单条. U s+ B+ T/ @/ s, Q1 g1 h
- ]);
3 V* R$ K1 u2 v' v% u1 P6 I - $collention->remove([]);//删所有
复制代码- 新" \4 u; B2 ~8 E# f, o5 D
- $result = $collention->deleteOne($condition, $options);
& T1 D S9 l2 N - $collention->deleteMany($condition, $options);6 X- k) A; u+ A) I) O G
- 7 ]4 p1 z6 K& n/ a: b8 V
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
l' |( k R! ~' I/ W. ^% R - '_id' => $tableName//我在自增表中用其它的表名作主键/ u% w+ Q! R& y8 S; c& L
- ], [. k$ I3 N Z# q! N; {
- '$inc' => ['id' => 1]//自增. W8 N+ N1 r( O! L# v: {
- ], [/ \: ~' N& g7 }' x
- '_id' => 0
3 U0 |" s# J/ _" a - ], [2 |7 J5 }- n! P2 `7 i% w
- 'new' => 1//返回修改后的结果,默认是修改前的; y8 a6 b+ Z* f+ F
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
- z, U. q; D; H - '_id' => $tableName
; C$ @9 e5 Z! j - ], [
$ N% p6 Q Q6 E* i, X0 @8 Y) A. L - '$inc' => ['id' => 1]
' D% o! x0 E5 A4 y - ], [* h r! J6 }8 a# W3 z: W" T P
- 'projection' => ['id' => 1],. l/ j# b% d$ o2 x
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
( u5 O; H, V- e* a- o - ]);
复制代码
- X( O h$ `, H) G6 h) }1 R. ?$ Z) q# T X6 M
|