|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
- \2 J( {8 j Y; b* o4 ] - - s+ F2 P4 D4 h+ d% k, G' K
- use MongoDB\Driver\Manager;' ^- Q- M- A" I7 d: _ Y# g
- use MongoDB\Driver\BulkWrite;0 s# K$ x0 N4 S& l" w2 ^
- use MongoDB\Driver\WriteConcern;
3 b! ]* U. f8 V% H& | - use MongoDB\Driver\Query;# d5 k; Z+ l, p, A: X: \
- use MongoDB\Driver\Command;1 ^' d C: K( Q4 k: b
- 1 O" X% S5 x' }3 N3 a
- class MongoDb {6 K/ y% X1 ^) B7 Z; J
( Y5 x# p0 c' b* G: z3 e- protected $mongodb;
$ l/ D% E, m, [( Y: Q - protected $database;
, d1 C, t* @% B. {1 N - protected $collection;
" w) X6 j" {! @; v. R& S: {4 | - protected $bulk;
& u0 C( k5 ^- E - protected $writeConcern;. ^0 v* n7 w; M7 N& ^9 c! s' \/ {% h4 S
- protected $defaultConfig
z( E' B: Q; L - = [
0 ~& y! m8 P( P9 }6 m - 'hostname' => 'localhost',
$ m S" ~7 ?; _6 q - 'port' => '27017', V- x# Z/ Q+ L1 Y& P- ?0 }
- 'username' => '',1 b" O5 m" O" R( e* I7 _7 P
- 'password' => '',1 k+ Q0 F5 T5 v# C! E
- 'database' => 'test'
+ c3 h# j* i& }4 k; U' P |6 w - ];
& ^+ g' N9 ?* r# t! k W: @2 j - 5 X. n! p. w q$ X$ \, x0 h0 a: C
- public function __construct($config) {/ [& K: B, f% Z# [1 P, Y' }- E
- $config = array_merge($this->defaultConfig, $config);. ?1 y' a) Z* o6 E
- $mongoServer = "mongodb://";
6 y: p1 L' a* E: c( E. }8 x* t$ d - if ($config['username']) {
- R; y3 R$ ^+ S7 s. I- X4 p9 I/ Q - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';9 i6 {; f' X4 G8 y" P4 N
- }
+ W: K2 q6 k+ C2 k0 s* w - $mongoServer .= $config['hostname'];
: _ w. Z) ?* m+ x - if ($config['port']) {
h/ Z+ t8 ]* N8 R$ j1 U. r, I6 Q - $mongoServer .= ':' . $config['port'];
/ M( F& i+ E; z6 [6 E - }
5 k" c! l1 W4 c+ ]; s0 W - $mongoServer .= '/' . $config['database'];
0 `3 K$ A+ Y- [. r8 l$ @
4 e" l0 L! @ X- $this->mongodb = new Manager($mongoServer);0 U+ r3 ?/ X" W0 M, G; ^' t0 f7 M
- $this->database = $config['database'];" A5 y6 Q" R6 n' {* X" a7 p
- $this->collection = $config['collection'];# ^; H% I b$ t. Y' r, @
- $this->bulk = new BulkWrite();
# m7 u6 B. Q" _* l/ G) v - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
) E7 |: n. Z- O7 @4 s - }
4 ?3 t- f8 Y) j) N1 ^/ c - 0 `. B" _1 D1 U- Y
- public function query($where = [], $option = []) {
6 ~% M, D: O* \6 q: h - $query = new Query($where, $option);$ O9 q7 D# D& x4 f. l
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
4 X, z. h5 O( _- I6 A2 x6 p - 6 X+ |% @4 K* @/ x; F. L& S
- return json_encode($result);
; n5 ~* w1 i3 w1 r' L" O% D6 D6 m - }
6 I" ?6 W; j. C Z) D5 z u - 4 r; M8 m' {% v" O% L2 j
- public function count($where = []) {
/ w0 _# N( ~3 Z- v" p7 o6 \ - $command = new Command(['count' => $this->collection, 'query' => $where]);
0 {6 X ?4 O, W - $result = $this->mongodb->executeCommand($this->database, $command);
9 d% u7 Z+ I* y3 J9 U, Q - $res = $result->toArray();
" \: \9 O0 w0 W. [- L - $count = 0;
$ @* h3 Q1 j: ^3 t+ d% E( d - if ($res) {
0 u2 o% j4 ?7 ? - $count = $res[0]->n;8 Y' ^. v# M+ V
- }" b9 [' l( p1 }" P" x
- 7 W9 Z* ^6 V* @3 O1 z3 _& v
- return $count;
" A# `. J# o0 } - }
$ q! X5 Y: ]3 B" B - 5 j5 {+ q2 C2 P- i, Y% y6 a5 M; a
- public function update($where = [], $update = [], $upsert = false) {* K5 G: A6 }; t
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);+ y7 {% w" R8 V5 d8 m0 W* i
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
4 D% t" w, {! I( S; S% I8 l3 Y- w
; g/ v, X5 n9 [3 c, T9 u4 A9 O! ]- return $result->getModifiedCount();: X @& ? m2 r* n; I
- }8 m. e1 o$ h; ]5 W/ \1 T
- 5 Z( x* V, @1 m, N
- public function insert($data = []) {# S0 H- W7 y% T! Y+ p) L9 y
- $this->bulk->insert($data);
7 J" ]& b* J5 l1 w' W, k! }( n - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);, r; ~- ]! h4 S, L% J
' @$ G2 M& Z6 w% r% k" K* j, ?- return $result->getInsertedCount();
0 M- I- m6 t! a2 X& A7 D/ W7 j5 Z - }
: b" S- G* n) M7 X$ I7 B: E/ T+ d5 W - , n7 G/ x2 B' L: X, N
- public function delete($where = [], $limit = 1) {
# [8 n& Q/ ]: H+ E" H' g - $this->bulk->delete($where, ['limit' => $limit]);- G' X% h8 A4 } u
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
; Z2 v6 O& Q1 ]9 ]
9 o, U# l+ `2 h, O% K- return $result->getDeletedCount(); p3 R7 j1 f2 n" \) V1 o
- }
4 }' K: _8 |; @ V0 L1 \ A - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单/ i& D% O7 P3 p2 n0 m2 T; h- }
- $lastId = $resultOne->getInsertedId();0 j) b; Y$ O. i, D4 a) R2 y7 _
- $resultMany = $collention->insertMany($array, $options);//多% U( d$ r2 B- \4 z) C& l, I2 I
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
# k7 X$ y) ~3 i% `! Y! j
- $collention->update($condition, [! i# k* @! m4 A% @9 H _, w
- '$set' => $values
) V4 B7 N# R6 w( f - ,[
7 L+ o a7 ?, G7 J: ^) q0 Y - 'multiple' => true//多条,单条false) r% V8 V( Y( d5 l% T
- ]);
复制代码- 新0 {) _9 Y: U* y" m% ~' r
- $collection->updateOne(
& z8 T5 d) _ J: h& T - ['state' => 'ny'],* `9 M8 [0 h2 S9 e% b
- ['$set' => ['country' => 'us']]
' P# O1 W! X+ E' Z! f - );3 _ p& s& {$ g& w* j' ~5 l
- $updateResult = $collection->updateMany(/ u. I, ^- U1 E5 V4 K
- ['state' => 'ny'],( k; W' B9 x1 [* D! \# }- S
- ['$set' => ['country' => 'us']]
' {+ r5 X% I. s. D3 c - );
! r8 U! O+ q" ]; B( v# m - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
6 J/ \; i- J( N, g3 y; ]' S6 h* ?" h
- $cursor = $collection->find($condition, [
! Y, Z& a C$ R; t8 t: q8 x - 'name' => true//指定字段" m% i1 i+ t- X: z
- ]);
8 `6 V: L" @, M$ Q( H0 t# K3 F5 M* \ - $cursor->skip(5);
' S3 W F) o6 A: t( d3 p - $cursor->limit(5);
5 j8 ?5 ?1 n* x9 ? - $cursor->sort([. [7 F6 F, x7 ^8 R8 }8 L/ L1 p) Y$ F5 G
- 'time' => -1( l( l H) F, P5 f% i5 R- x
- ]);
复制代码- $cursor = $collection->find($condition, [
. \, p1 Y) |% D/ D, b - 'skip' => 5,4 N8 {- c( k; ?' _6 _" x
- 'limit' => 5,
3 x$ @9 A; E5 Z3 f# ` - 'sort' => [
: m; z/ y! m) Y% }- @ - 'time' => -1$ \/ X+ ?3 A8 ~/ l# b7 ~
- ],//排序
! |+ c( f8 V. B - 'projection' => [1 G9 ]1 R$ `& M R+ H* K
- 'name' => 1//指定字段* k/ E7 b1 y) h. L H( M) M: c4 [
- ]8 `/ R9 W; y% U" L: k
- ]);
复制代码 5.删除- $collention->remove($condition, [
$ j; @5 w, e: O3 i" a/ ~/ u, s - 'justOne' => false//删单条
' y/ S9 w! z2 M: o. y+ G - ]);! C9 T2 Y, `2 Y( Z) L
- $collention->remove([]);//删所有
复制代码- 新" |2 j6 E" N( p+ V# P! M8 a+ k- |
- $result = $collention->deleteOne($condition, $options);5 u: o7 l0 i5 C( m# t
- $collention->deleteMany($condition, $options); q) j+ ^- V5 F' f, m
4 u1 Q7 p$ I2 i$ A- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([" z8 c; M) a' |
- '_id' => $tableName//我在自增表中用其它的表名作主键
5 Q5 w; j: G6 Q/ D; d - ], [
1 M% ?- V& j9 y7 B4 p5 V* x - '$inc' => ['id' => 1]//自增
% T* f: l& c1 G* J; f - ], [3 y1 K6 X& Y, P3 t9 }
- '_id' => 08 t n7 A8 z5 X/ r+ I: ~
- ], [
9 d. {9 J+ _9 x: z4 @, U( M - 'new' => 1//返回修改后的结果,默认是修改前的
: P0 o7 e4 K% b4 R1 w - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([- x; Y% ?2 v6 @7 \& \
- '_id' => $tableName
: k; E5 Z# v6 d2 C& o( B - ], [
f# j+ _" ]0 ` - '$inc' => ['id' => 1]
: |+ R- F% U/ v2 } p" l - ], [" O. v5 J- M3 p Q: }
- 'projection' => ['id' => 1],, v; A- V' t6 n8 I9 b. H
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
# R3 j- `( A7 h+ _; L9 x - ]);
复制代码
9 {1 R. J) X: j4 O: Q/ f: I7 h1 P; ~4 B
|