使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php/ Z' w! Z$ X s
0 p, r# F+ M% [) s- use MongoDB\Driver\Manager;
/ ?; z6 K- W! q; k; j, { - use MongoDB\Driver\BulkWrite;+ f& G4 Y/ x+ n2 x, ^
- use MongoDB\Driver\WriteConcern;* v8 r$ J( l. ], [
- use MongoDB\Driver\Query;
2 X1 y9 T: c' I- p, }% x6 R) V - use MongoDB\Driver\Command;
0 x" p, X1 c6 N s# C - # h6 F6 l3 f( r7 M* @% l
- class MongoDb {
% Z p& H" T7 Z/ _8 z4 u - o2 ~! I/ r4 a/ t9 p: H
- protected $mongodb;. m# \9 S7 H! K+ Z9 d
- protected $database;
1 A/ O2 Y; h& h+ ~; ` - protected $collection;
/ ~6 G/ n- K+ D+ |6 x - protected $bulk;! s3 T. j5 I) P, _1 A2 }: u
- protected $writeConcern;, ^* T' }; q0 c/ ~) h
- protected $defaultConfig6 Z% I; M1 V! @6 c0 i: Y( |1 y
- = [: F- u2 V: ^2 c- }6 Q6 m
- 'hostname' => 'localhost',
; q6 u; i5 I7 p9 J0 }4 B - 'port' => '27017',
! i& Y2 A7 T: P6 P) \7 ] - 'username' => '',
- Z. w* b u9 Y' Q- k - 'password' => '',* } \1 E, N c; U/ I. H
- 'database' => 'test'
0 t2 G) H# o7 h" h3 C5 y - ];5 g6 q% P8 z) K! G1 c8 l7 n6 P5 i- @0 Y
- : _8 X }1 r% w' l' j
- public function __construct($config) {
( A+ D# l* y0 c5 X - $config = array_merge($this->defaultConfig, $config);
5 D V0 S- H D, w) P2 d - $mongoServer = "mongodb://";
; j w# P E: }) W% @+ _1 p {9 z - if ($config['username']) { f* b9 l2 U4 j Z. g
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
% J, u0 y# I/ V F8 i! I% E - }6 {+ n! o9 N4 A' I* K4 [6 x+ \
- $mongoServer .= $config['hostname'];
& O) _( z4 u+ m - if ($config['port']) {
6 y( `/ ~1 e4 `) G* O( ]8 S- I - $mongoServer .= ':' . $config['port'];- c$ U; s2 E0 T* e
- }, T* p5 I0 f/ e8 T I w
- $mongoServer .= '/' . $config['database'];) @5 p8 K, c0 N9 o4 M0 A
9 i _1 Q& O" {7 B L$ y- $this->mongodb = new Manager($mongoServer);$ \& o8 t* R' j( \" a2 u, @1 d; Q$ @
- $this->database = $config['database'];
/ u/ c% x+ ~- W4 `6 W. G0 P - $this->collection = $config['collection'];
& F! D! w) x& `: `2 T5 D - $this->bulk = new BulkWrite();
% A+ J/ L! M0 P; b - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);" {9 E' [4 ]- e+ v; S/ f
- }* N% U# v7 ^4 s# d# |9 k: z4 S! B
- + G2 g* q! k" p! n/ m/ B
- public function query($where = [], $option = []) {( c6 |) w$ F9 r7 ?
- $query = new Query($where, $option);
4 C5 R: H3 @4 a1 g' e: X" l1 f - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
% A8 Y; A: ~) }+ v3 s$ O R+ l# L - 3 w) W5 o; w+ J. L
- return json_encode($result);( A; @0 l( [ t% M; M8 j5 r
- }% h7 Y, e2 g4 T; G8 {* v
; s$ N4 K. C* j; k- a# ?* y- public function count($where = []) {
4 q- x2 K3 c) Q" e* c s - $command = new Command(['count' => $this->collection, 'query' => $where]);
! Y6 j/ ]+ B: P d - $result = $this->mongodb->executeCommand($this->database, $command);
1 {7 E: C$ i! v1 q6 _' X! y - $res = $result->toArray();
: r# k7 z) x3 p - $count = 0;7 f6 [5 D7 n( O% u" v
- if ($res) {
) v9 |% v" G2 M, w$ @0 U3 J$ m - $count = $res[0]->n;: k- d4 v. r. C+ a! i( K
- }( i" b3 T% c: E% O5 D
; b7 [+ O; }8 }" J7 z- return $count;
4 u8 p+ }9 F8 Y5 f/ { - }
& F; f m, p4 U - ( F7 F& V2 b0 v& v5 |
- public function update($where = [], $update = [], $upsert = false) {
* w2 R9 [5 q$ ]+ s - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);; t, _. n, b7 n6 k# _6 A+ m) t3 n
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
% M% l4 Z$ N* m7 x; z' q
8 T: Y, W3 K" W) ~+ S- return $result->getModifiedCount();
, A6 A3 `% t. { - }7 A2 _; f% x; s1 N) C7 H
7 O8 H( d8 O0 ]/ \& W' l! H- public function insert($data = []) {4 i) S1 \1 x, N5 I& C5 i
- $this->bulk->insert($data);6 W) X( W" p+ Y, t' s
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);9 U& p# c7 z! W/ m+ N6 R9 C' A% M
5 u1 h! e4 b3 z- return $result->getInsertedCount();/ ?: L+ C( h9 L8 X% {, e7 M6 D* o
- }
# n# p' K) }# C7 p# n3 V6 O - 4 K" B! ^9 a7 d+ z; G9 C
- public function delete($where = [], $limit = 1) {
, T, y+ N# s) H6 L0 A- l - $this->bulk->delete($where, ['limit' => $limit]);0 [# P: n# U; A# `4 g# c/ f0 s7 C
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
; y7 g4 ?" Z( f- |% E: O! A! O' V
3 W4 U* y5 ?$ F) | S* i- return $result->getDeletedCount();
) _, Z% P! V3 {3 ] o2 F* i - }4 ^4 l+ ^' ^& B' g: j) V- r
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
0 X5 O$ y6 _+ K( C* \/ i 2.新增- 原
7 ]! ]# M$ G. f! u. F5 V) ^0 e
- $collention->insert($array, $options);
复制代码- 新
# @6 I- {2 ~4 T! D) g* I3 C
- $resultOne = $collention->insertOne($array, $options);//单* y2 }/ }3 H/ V$ l% J3 Q, X; ^
- $lastId = $resultOne->getInsertedId();
% i2 _' j4 n5 r/ h6 X& {! f( s- Z - $resultMany = $collention->insertMany($array, $options);//多
" }' T! x9 h) y( i - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
3 A( |( s) ^. r3 ~! l: C
- $collention->update($condition, [
8 w& V- k' V+ E - '$set' => $values: U* w# b) |: P0 |( J& v
- ,[; v- O0 ^' S& G
- 'multiple' => true//多条,单条false
$ X: ] T3 U, r2 N( i - ]);
复制代码- $collection->updateOne() X, F. |* K- l& r" s; ^
- ['state' => 'ny'], ~6 e* u' W8 b+ t; a4 E7 E
- ['$set' => ['country' => 'us']]! V9 Q3 W5 {5 V8 M5 `: X: f
- );
7 B2 ~% {5 C1 K7 F6 N" ^ - $updateResult = $collection->updateMany(
. S# T4 s8 } a* @$ k, a - ['state' => 'ny'],
( v/ ^* I2 j( N/ | - ['$set' => ['country' => 'us']]: e% {" j! f* P4 U; S4 _1 E+ B
- );
9 Z% W# d5 f* f* J+ b - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
% R9 e' s2 D/ ]: Y0 i5 u
- $cursor = $collection->find($condition, [, V9 E' a# o1 I9 Y) P$ w7 q
- 'name' => true//指定字段: B: B0 c& I) ?/ [; N0 z
- ]);3 O. r6 c0 w+ |6 {% M+ u
- $cursor->skip(5);
; k( E; s/ V" e - $cursor->limit(5);& R/ `4 o$ f' s& X% P! u# ^$ ^
- $cursor->sort([- l- A1 o7 T8 _1 N9 v% q- [
- 'time' => -1
8 t; X5 ` q3 [7 N - ]);
复制代码- $cursor = $collection->find($condition, [
) b! `( |& h" H5 |+ W, k - 'skip' => 5,8 D7 \) ~9 ^+ w3 l, a
- 'limit' => 5,
% h0 b! R. S1 f6 g+ Q I5 V - 'sort' => [; Y5 y4 @& ^+ Z8 E# y+ B
- 'time' => -1, L! s! ?; N! q) A/ l- }. B# M
- ],//排序. ^7 ]% A8 n4 C) v) k
- 'projection' => [7 T# T. W. f; D6 |" ~1 V) |( e2 O
- 'name' => 1//指定字段
: q6 i* j' C' T# Y& L1 K# i" A - ]
) G! R. |9 a7 w" \ C! R - ]);
复制代码 5.删除- $collention->remove($condition, [6 v5 R/ N/ x$ B
- 'justOne' => false//删单条
* |% _. ?* y/ o) W9 n b - ]);
3 ^! Q U" s9 |- V) P: \+ y - $collention->remove([]);//删所有
复制代码- 新( [0 h1 G6 ]9 j# p. q0 {- A' p3 A) L
- $result = $collention->deleteOne($condition, $options);2 ^, F, }! M8 ~* _$ f1 M
- $collention->deleteMany($condition, $options);
; b4 u9 {; Q$ Y& w( o3 s$ T - 3 \) u/ x9 p7 ^& F3 {
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
( i5 r {$ R9 m) L - '_id' => $tableName//我在自增表中用其它的表名作主键
9 ~3 m4 A1 [5 F3 j - ], [. V; c" u4 l7 ~9 T2 D7 [
- '$inc' => ['id' => 1]//自增
! \5 G0 h# S- E0 r$ J - ], [
9 _5 i& Y$ T! N - '_id' => 0
3 k, i# N! j- S - ], [! H8 R3 R3 L6 Z9 N
- 'new' => 1//返回修改后的结果,默认是修改前的
: I1 R5 T b7 g8 h- N* F: N - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
1 r6 i! q, B! Z" W# l6 `3 d - '_id' => $tableName: H% I. j: Z6 F' M% e1 w$ r. ?+ X4 w1 m
- ], [( X7 \# f( D; l1 }
- '$inc' => ['id' => 1]1 Z/ L9 n9 `: f4 U% p
- ], [: }3 o+ b9 }3 P* [, L+ @1 e) q
- 'projection' => ['id' => 1],0 U+ O9 Z+ E X; f
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
9 R0 s7 Q# k- `/ z: j, I - ]);
复制代码
5 z4 M& y3 t! ~
. k4 r9 ]4 ~1 i# V9 w( _+ Q |