|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
4 r W/ U x- d
9 M, W% }. ]" q- use MongoDB\Driver\Manager;
& G7 D3 C% |# h, V( X/ ^- { - use MongoDB\Driver\BulkWrite;+ t+ n: Q: c) u8 H
- use MongoDB\Driver\WriteConcern;6 M1 H5 H6 O4 [9 O7 I
- use MongoDB\Driver\Query;: x3 |7 ]( `( r
- use MongoDB\Driver\Command;2 o8 b( _9 V! u6 Y6 r
, h5 L4 x* q! b I$ m2 A# O- class MongoDb {
1 D$ B, J5 ` ~/ O - 7 b0 \! M j# u3 J5 m2 o. ?( ^
- protected $mongodb;
X/ q) [; E C - protected $database;8 _) P0 M5 q. S4 ^' E8 y
- protected $collection;
1 j2 f$ _9 x* ]3 n - protected $bulk;
) |1 \% j- L) d% O+ E: J9 w) K# T - protected $writeConcern;/ l) ?3 M# ]) c1 c- g
- protected $defaultConfig
; X, \/ i, _+ c# ]% [ - = [
4 ~; t6 n# A8 {4 e0 u - 'hostname' => 'localhost',; W4 w# @9 l+ L1 G: Z$ D
- 'port' => '27017',
" ?: O: B+ p2 b1 K7 [4 p - 'username' => '',
* g3 ]0 S5 ` n2 e1 U8 M - 'password' => '',
! q- p E {7 ]8 C: B9 k: S - 'database' => 'test'+ G/ Z# R2 z+ q2 W; M
- ];" ~$ I5 @8 J. u5 n+ b
- ' G0 d6 x* V/ Z2 @0 W
- public function __construct($config) {
! X) ?: q" @' `8 n2 H' J - $config = array_merge($this->defaultConfig, $config);
y# t& u7 b% O9 a& x - $mongoServer = "mongodb://";/ D2 y2 g2 B- C( B/ J+ M, k; |# c4 x
- if ($config['username']) {: Z9 N9 \& a, W8 P
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
0 b4 C) N$ w: l3 g7 B* { - }/ Y. K- J! ]; U, | Y7 {
- $mongoServer .= $config['hostname'];+ O- b' u3 f. D0 K
- if ($config['port']) {
# w7 x' L V0 d7 ~6 D$ l - $mongoServer .= ':' . $config['port'];+ V& V, [4 }$ s7 g- R
- }
. l4 Q! y! t( `0 |- P O - $mongoServer .= '/' . $config['database'];
+ h" S7 e" S& k m' Y" a4 T- \- j
* e7 i, ^6 k1 T- $this->mongodb = new Manager($mongoServer);& L/ b2 K m0 [$ \. \4 y e
- $this->database = $config['database'];& {; |3 s& A% o/ H" i& p- x1 R: R: {
- $this->collection = $config['collection'];, i, C9 a4 r$ ~5 E6 h$ R
- $this->bulk = new BulkWrite();
: X6 ]. _+ ?' @- y$ _& | - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);( l `: P1 I1 {2 x: N0 b
- }0 D! V) u% l- x/ U: p
- , e& |* [# f! e: x) ^3 e y
- public function query($where = [], $option = []) {
# y2 x1 K. B# W2 ?2 p5 f; t - $query = new Query($where, $option);
! P T. r) p$ O$ l! [6 n9 R" d - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
+ t) {2 [" P9 L% A% f+ @' W- O8 x
8 I0 U# t% N4 m( b- return json_encode($result);
! `2 k- M" \! v9 t' Y: L; c' ~ - }
, l$ M5 X0 B. W3 I( W& N
! H* ^* v' W; `4 l- public function count($where = []) {
1 N [! O) h! Y0 ] - $command = new Command(['count' => $this->collection, 'query' => $where]);* ^0 g& F' D+ ~6 d# ^9 i" Z3 I
- $result = $this->mongodb->executeCommand($this->database, $command);# `; p- T) ?% _ d
- $res = $result->toArray();2 ]4 P, q* g% n* J6 E$ ^
- $count = 0;
& \: p, w* `8 Y, ]0 i) e$ g, f, A: `9 x - if ($res) {
+ N z4 ]+ v' d. A - $count = $res[0]->n;9 P1 I4 e9 T% Y
- }
) t$ E: ]3 |) Z, V0 F$ n6 z - ( N" W' E* g0 l! b4 h% w
- return $count;
0 q+ L8 N. w$ V4 h. J4 _' y. _' { - }& K; H0 a- c: C4 n
3 @* C# e* i0 ?' {, Y8 ?- public function update($where = [], $update = [], $upsert = false) {
% o( B7 m$ V2 t& U3 C - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
# V0 }5 K& e; l5 `8 b - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);/ R% ~2 o. t4 j! y' s# i
]: |; ^) X" v9 I4 h6 t- return $result->getModifiedCount();! ]0 z9 h+ s: i
- }. k1 P, A' V' c$ ]. E4 j" {
- 2 n& P, z* m$ G' A. J, V8 E( a" i
- public function insert($data = []) {5 _! t# z, K9 y* M9 |5 E
- $this->bulk->insert($data);( m' W6 f7 W0 b: X' J$ ~
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
, w" e9 E) W9 f( s% E
/ s% e; s8 ^" U' g6 ?- return $result->getInsertedCount();: m% o0 S: w+ M2 W" |- d2 x- o
- }
' ^. k9 M7 F0 w% P; }6 `
# w# X! N9 \. t5 V- public function delete($where = [], $limit = 1) {
) k3 D" P0 [& i" m! v - $this->bulk->delete($where, ['limit' => $limit]);& ~3 Q# x# ^6 b
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
( {! D3 X0 Z, I4 l# s/ X1 \! E
6 u" Q ?( | I: J% \" ~- return $result->getDeletedCount();! h$ T3 l) R$ _' k3 T% V( S
- }
8 {/ _6 E. [- z/ I4 a5 l - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
3 O G5 ?- D& B1 b5 y5 \7 V7 O% O - $lastId = $resultOne->getInsertedId();6 d, o, |3 H! i" b% e
- $resultMany = $collention->insertMany($array, $options);//多% H+ s2 w* R; m* d# X
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原* n- a/ s; g7 B. W4 @ n" _4 [
- $collention->update($condition, [4 r7 k: Y) K9 i$ e
- '$set' => $values
% @% R6 A& S; p2 y - ,[6 s% V i3 P. N$ b5 l' @
- 'multiple' => true//多条,单条false
( `' \' J% j- F( h. ~ - ]);
复制代码- 新
3 u! j1 U9 p! R) [* J. u- Z7 ?
- $collection->updateOne(
4 P" w: y) o5 S: Q C! t1 s; l - ['state' => 'ny'],0 m6 e/ n) G6 k5 F* E& A
- ['$set' => ['country' => 'us']]
* D: H$ Q' H: j! D7 O& F - );5 \1 B7 K/ T$ a
- $updateResult = $collection->updateMany(1 A$ e# K8 J9 R- M1 f
- ['state' => 'ny'],! M, z3 r) _8 }2 }8 @
- ['$set' => ['country' => 'us']]8 h0 Y% Q7 E* E3 [/ R/ c7 l
- );$ z9 |( ]& I4 k# R" ^7 b
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
' K* Z/ z' Q) R1 a - 'name' => true//指定字段
. L! u X9 R+ q' L - ]);
$ ~& Y' f4 P) ~1 t/ a2 H' ?+ I% N - $cursor->skip(5);
! q6 ?' ^$ C8 w! A- p( s. s7 Q6 z* b - $cursor->limit(5);
% E3 R0 R8 L( t5 m$ Q! x - $cursor->sort([
6 m ]* ?9 X# V8 W1 i. j - 'time' => -1- b$ w' [! B, [, j6 S! N
- ]);
复制代码- 新
; [5 V3 A1 F; _( t/ T% w9 P
- $cursor = $collection->find($condition, [
7 |2 C( ?; E4 F5 @ - 'skip' => 5,' Z0 s& ?% P& K* g R# D9 L
- 'limit' => 5,
; m* M# p. `: ?7 | - 'sort' => [
8 b* G" h% X1 r- }1 | - 'time' => -1- Z* P% d+ `$ Y2 [2 C) l% n
- ],//排序! m! L+ e3 l, w& _8 G
- 'projection' => [0 H4 P6 L' D- u0 u0 \
- 'name' => 1//指定字段+ t. f% R+ Z. t
- ]4 F* w$ P$ G0 q# ?, `- Q" [# A3 q
- ]);
复制代码 5.删除- 原
1 F2 M) e5 Z, ]! K% `+ O
- $collention->remove($condition, [" E) Z5 ^* O" n' g1 a G
- 'justOne' => false//删单条' `) i% J/ M- p6 @# H x
- ]);7 d# N% C, k1 D1 ^/ h7 f+ W
- $collention->remove([]);//删所有
复制代码- 新
4 w2 \7 [" F+ \& _6 Q& |8 x. u
- $result = $collention->deleteOne($condition, $options);* x( T# V5 `3 ?) S' M1 z m0 u
- $collention->deleteMany($condition, $options);7 a2 _/ |' S5 ^6 N, h, J8 ?& j
- 1 l$ r6 }2 a" J. E& {# z
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
( [8 B( C _3 j4 q, n - '_id' => $tableName//我在自增表中用其它的表名作主键# j9 j, _' E7 p: E, ~( P2 X
- ], [! g0 z1 s' v4 }4 _" r% Z
- '$inc' => ['id' => 1]//自增
! u* `' |8 r- D( h - ], [& p7 H2 D4 K& e* d D* E' m9 }3 p
- '_id' => 0
1 R c, Z' h5 s& X' c - ], [7 e1 C/ F3 g* g& K5 ?# T
- 'new' => 1//返回修改后的结果,默认是修改前的$ j) p7 u/ [# _' |
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
* ]; l# Z( N2 m8 c8 ~+ N: ~ - '_id' => $tableName9 Q8 `1 h$ O; E: F
- ], [9 J: z9 }! L8 J. S
- '$inc' => ['id' => 1]* h, K* x* z# Z" T% S: R6 z N
- ], [6 q0 j; v0 H: z: C
- 'projection' => ['id' => 1],
: s% S: B K2 N. w( T8 \1 w" N - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
0 [! R$ {. I$ n - ]);
复制代码 3 }( H% h- s! r. ?
4 X. }& T0 u: l, S
|