使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
2 ]& r' D1 }. e8 Y% S4 Z8 |: r& W - & j0 k# i% t. P5 ]
- use MongoDB\Driver\Manager;
* b( O6 c; R p; I* _ - use MongoDB\Driver\BulkWrite;
5 L+ D5 R" r: G I4 y+ a; V; E - use MongoDB\Driver\WriteConcern;
$ `. G) ] ]& R( L Z4 w% V - use MongoDB\Driver\Query;% H+ t. w( F" J1 G& M
- use MongoDB\Driver\Command;. a$ o/ d9 X4 A7 p" o1 F3 D3 B0 A
- 1 ~( _0 ^& I' M; W- {: N8 ^. `# u, N: S) T
- class MongoDb {% I# E* M# y6 p6 n5 q
2 X% U& g0 \) c- protected $mongodb;
) V P3 q0 [, c( [- Z/ L - protected $database;
# r* y" i; e4 u4 S! L$ n4 x) k0 | - protected $collection;
$ g: x V8 o0 x - protected $bulk;0 j, q- m& a: C3 @7 q5 M
- protected $writeConcern;7 _/ O0 V' K6 N2 C
- protected $defaultConfig+ Y1 f( d: Z5 @! g$ n
- = [" M1 s4 V1 D% k+ E$ N2 Z8 k+ [7 N
- 'hostname' => 'localhost',
; I2 Y! V7 T4 e* E( ^ D9 i - 'port' => '27017',
( C9 b, J: m6 l9 I& t- K& W - 'username' => '',
# o6 b1 D8 g. C0 b' l - 'password' => '',: ?+ N: j a- ?$ W
- 'database' => 'test'
, S5 t& B, \ k3 W3 Y - ];
9 Z8 i E2 ], D. A$ ?& E7 ^! r
- ~3 Q$ k4 j! c/ ], G- public function __construct($config) {
, [! [5 G( ^3 {/ o - $config = array_merge($this->defaultConfig, $config);) @7 \' l& ?5 A. u6 x* P6 f
- $mongoServer = "mongodb://";
: J9 {6 q/ o( W+ B( g1 ` - if ($config['username']) {4 r6 B) i; v3 ]3 V
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
1 G# ~/ ^3 E1 y( H$ L1 d4 t8 F8 s - }
" L: [ ]& g! l% c - $mongoServer .= $config['hostname'];5 p+ R# D4 a$ q/ y) t
- if ($config['port']) {
z' D, l+ y0 E F - $mongoServer .= ':' . $config['port'];, [ d$ [. [; Y, @1 R6 R4 ~
- }( o+ g+ X6 N) W/ g4 R
- $mongoServer .= '/' . $config['database'];! b# k* U; J) g( t5 x
& S- J4 f: E A" A; I% Z- $this->mongodb = new Manager($mongoServer);
2 M5 B9 ?: `8 t7 n! G! } - $this->database = $config['database'];
8 |/ I2 j; M5 B9 z; R- L+ X - $this->collection = $config['collection'];
* ?9 H5 l5 J; f/ p& i - $this->bulk = new BulkWrite();
! p2 ^/ C! r) i2 L - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
/ s. O$ d) k/ o - }
/ `4 k; C8 k" b) ~; X1 S
$ n; H& q4 @# @/ y- i- public function query($where = [], $option = []) {
+ f1 v' h6 \' ?0 ^& `1 M' t - $query = new Query($where, $option);! N, J- D5 c; b: D# I
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
, j d7 G$ J" L6 \+ L9 f) f ~6 R
5 V7 u: n$ Q! P6 `, e+ h- return json_encode($result);* E% N. j6 _0 ^# {- X
- }& O% U) }% T( Q$ X
) a1 D+ I/ m+ F4 C; R- }& \- public function count($where = []) {
( C% U$ {1 _) n" l2 r+ J5 X' T - $command = new Command(['count' => $this->collection, 'query' => $where]);9 p/ U7 e7 k8 c& _$ y, B# v
- $result = $this->mongodb->executeCommand($this->database, $command);
, Z0 j. _8 E* i - $res = $result->toArray();
7 @4 |* Z5 w6 ~* n; r. {% m2 e R - $count = 0;
! Y& w, S* c0 N4 u; [# w5 ~ - if ($res) {
4 M8 c& l5 {/ X6 |. N! W, { - $count = $res[0]->n;
: P+ ~, n6 w9 U( X" t) {( [ - }
8 P$ W4 \) h7 f - + b/ P0 p3 L% w: S
- return $count;
# A: P! A3 f4 L. T1 \ - }) ~. J \' B+ D1 w
/ _4 S' {1 p k4 N6 b# W$ p- public function update($where = [], $update = [], $upsert = false) {
( T8 g+ M' ?( U- s; E( S0 S# V - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);' Q c: [. |' R. A1 Y' J4 E" }
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);' t# ?( ]9 Y- E# P8 [2 z
9 u5 O/ c4 u' X9 t- H3 L! }- return $result->getModifiedCount();
7 P* w# X. v! x: U - }7 j5 [+ b9 F5 G2 `
- 0 Q( h7 u( N8 A
- public function insert($data = []) {0 z" A* Q v. x
- $this->bulk->insert($data);! z3 P+ o n0 y+ @' w
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
\2 h3 E) P3 W5 e# B h# b) W! O - d9 Y$ e5 K5 f* B7 Q
- return $result->getInsertedCount();. }5 i: ]1 k* G9 z% U
- } Q. m9 z! o9 u/ U5 B# O
0 o1 U0 I t7 k6 i. R, U- public function delete($where = [], $limit = 1) {* ` `! _& d9 F* v/ p, O0 @' q- v
- $this->bulk->delete($where, ['limit' => $limit]);/ X5 |, d! y3 z2 @$ y
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);0 e1 n# L% r, z! c Z( I
- ( Y" j2 y2 t" ]4 N
- return $result->getDeletedCount();8 Y: [, P1 j! b
- }0 }5 {' l. I& s* X9 |
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单4 g: T# s+ G! X: ^1 A
- $lastId = $resultOne->getInsertedId();# e! i3 [4 B O! J7 h
- $resultMany = $collention->insertMany($array, $options);//多6 {+ c2 p% v" _. S1 W2 X B( d
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
2 W. M! x# g! o+ L8 y2 u) V( m8 o7 M
- $collention->update($condition, [2 F* B2 P. a' t% r( ^. ?
- '$set' => $values/ B4 H0 f$ i- f+ t' }
- ,[
( P5 w; F4 F4 s& M - 'multiple' => true//多条,单条false
% v2 W. l5 }& ?4 i& O4 \& P& y, Z - ]);
复制代码- $collection->updateOne(
" E8 k2 q, [8 \+ O6 @ - ['state' => 'ny'],& \! ]9 M, _# }# z" t) E
- ['$set' => ['country' => 'us']]
# `! b: x( b& H4 b - );/ M$ W$ F3 o0 |; Z. Z
- $updateResult = $collection->updateMany(
. k6 _) F% x! L - ['state' => 'ny'],
: {( g# ]1 n; A4 z) t# o; C - ['$set' => ['country' => 'us']]
. r* u$ C: s o( V - );
/ K. F; |4 H9 q$ P8 u - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [ X* Y( x! L w7 d, s
- 'name' => true//指定字段+ X1 _/ i( W9 y8 a( e3 p# D# |
- ]);% l! i5 y/ v! ?# G Y% k
- $cursor->skip(5);
0 b7 w4 l2 T- |' u1 P+ w - $cursor->limit(5);
3 A! O, c9 f9 Y: w$ k - $cursor->sort([0 H* F5 @( t: [' ~
- 'time' => -1
( I+ O9 K. Y$ b. `" u% j( K. X - ]);
复制代码- $cursor = $collection->find($condition, [
9 k7 h+ \8 Z* e9 t6 f - 'skip' => 5,( f+ _) h8 q" ?" h5 L+ @
- 'limit' => 5,
* ^! ?7 t9 p3 n - 'sort' => [0 P3 N1 @- P; w* P- Z9 `; J8 Q
- 'time' => -16 r6 n3 U y7 m3 D5 ~. U
- ],//排序5 _ M0 n4 C# S, P! H7 j) o: S9 C
- 'projection' => [7 O8 W& z, g# L/ t0 J. F) r/ |3 e
- 'name' => 1//指定字段
7 U2 w/ I/ T* v. S; | - ]) `' F4 Y6 K0 X3 f, y) G
- ]);
复制代码 5.删除- 原. c0 \( W" e! J6 |; l0 ^" z
- $collention->remove($condition, [! ?6 ]! c3 f( Z/ G; `
- 'justOne' => false//删单条. L$ U& S' Y' E; Q T
- ]);
6 S2 G& }9 u. D! S8 P: }) { - $collention->remove([]);//删所有
复制代码- 新
5 p/ ?& E( S& {2 A% U1 L5 Q
- $result = $collention->deleteOne($condition, $options);
# x) P' `5 G K N4 e& B - $collention->deleteMany($condition, $options);
. W* p: Q& a2 L/ O - ; V S9 H8 Y) M
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
$ p5 r# j" Z/ x. t9 q - '_id' => $tableName//我在自增表中用其它的表名作主键
( X) u1 d2 O/ S7 {6 L - ], [6 s" w9 S, m# }* @3 _. W: o+ T
- '$inc' => ['id' => 1]//自增
5 }0 P" e+ E. T. t - ], [
5 i! s2 K* s5 i - '_id' => 0
. ]2 S5 u; q8 N0 ^3 C+ S l - ], [" G- U; A/ n* O+ H
- 'new' => 1//返回修改后的结果,默认是修改前的
5 b {1 u. i# t% v2 f3 x8 N5 O - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([- E, a9 A5 S0 l! ^( N+ L
- '_id' => $tableName4 `+ v9 U2 W: e. J. P1 ]/ u
- ], [: u5 |7 B2 ^2 C; Z
- '$inc' => ['id' => 1]/ Y7 h# S: w; ^* U/ a3 L K
- ], [
B' A0 ` D* T7 K# m - 'projection' => ['id' => 1],
! G; m z0 D" Y. [' \% R T/ D - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER8 r' p( d- ` Z
- ]);
复制代码
/ V6 j/ O4 H' S/ o* K1 {) @, g& B$ _! k n, @7 @- X9 u3 X9 d
|