|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
. _3 z3 m4 I( {5 @" t# y - : U5 R9 ^3 i2 p
- use MongoDB\Driver\Manager;
9 R0 ~( f; F* } - use MongoDB\Driver\BulkWrite;
" A. @3 h; C, [/ Q" j - use MongoDB\Driver\WriteConcern;7 z' ~2 \4 X& F$ W% J0 w- ]
- use MongoDB\Driver\Query;# p4 |% w; u/ P2 t6 p$ \2 M
- use MongoDB\Driver\Command;" q0 Q3 [ e5 E3 X1 u
- . g1 Y# `, k6 }2 [. M
- class MongoDb {
0 b9 [% M: r% d, {% n5 M
. X# c: d! @& @& x6 s- Y- protected $mongodb;
1 L& [! n. U' ]( R* z9 [! m6 m0 |3 A - protected $database;
& K: [$ T* i* Z$ S- {$ g - protected $collection;. N9 Q6 ~3 a. W9 i Y0 b' S
- protected $bulk; h8 n5 B) q* W8 D
- protected $writeConcern;7 ] \1 Q( G* Y( w
- protected $defaultConfig
4 Y; W O" O8 x3 x* [. k" R, ] - = [1 j3 Q( r* i* f7 q4 h |
- 'hostname' => 'localhost',6 h- A- [+ m: @% Y7 j* v* b5 q
- 'port' => '27017',2 u* S$ \; P9 G E: d4 i3 t
- 'username' => '',7 b8 p( K9 l2 v& H; Z* {4 l6 [( K
- 'password' => '',
( I2 g( O% J" H$ x0 s! { - 'database' => 'test': x7 k6 m+ i1 \ s' } P& N& {
- ];+ Q4 p) b. x+ x7 l4 {. E5 B7 p
- ! \) I: K4 @8 z) [* C
- public function __construct($config) {' @* q+ }- S" E8 m/ x8 Q% E0 B
- $config = array_merge($this->defaultConfig, $config);& r* a$ l2 \0 W( r7 u6 S
- $mongoServer = "mongodb://";
}) X9 N; ^ A - if ($config['username']) {
, a% G' S w/ Z1 q2 l" ~! r - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';, \/ l. M( C( ]- g7 G) K' W, V3 ~
- }
5 D- |) h. C# n6 q& t - $mongoServer .= $config['hostname'];
' Y, H t" Y8 P: B* Q3 h! p - if ($config['port']) {) \3 U: n5 |# w' {8 R
- $mongoServer .= ':' . $config['port'];
. p$ |# S# |6 M2 h v - }4 `. v' m3 R* g9 j9 D' B
- $mongoServer .= '/' . $config['database'];
; d* ^9 U: U4 L& Z( R
; |; E: A1 R4 A7 P: P* C- $this->mongodb = new Manager($mongoServer);
4 L3 E( a2 L N) [9 I3 \- ] - $this->database = $config['database'];7 N! V; G5 e3 s: Z
- $this->collection = $config['collection'];
2 G- `" _2 T+ g9 A; t' U - $this->bulk = new BulkWrite();3 m! b, i4 t) ?
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);% S* ]# O0 R0 N1 E9 Y1 m) K( W6 H
- }: H0 `$ Q0 W' [7 n: |" n! J/ t
# T* j( H$ `% v2 V8 d* S: ?- public function query($where = [], $option = []) {
/ Q6 [, i% O4 p, n- u - $query = new Query($where, $option);
- n3 F' c {; ~$ G - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);5 m, U, ]! _+ P2 P+ B
. N# E& ?3 N/ W) a. I7 [- return json_encode($result);
5 ]; x5 W( N: X! f; l - }
! G( ]7 F/ U8 s0 x
% g/ U( A- e: v6 g2 G9 P- p9 |- public function count($where = []) {
* i1 o7 i( Z7 j" N6 B7 O - $command = new Command(['count' => $this->collection, 'query' => $where]);
, p6 X/ Y9 T, I" f8 x9 f- Z, O - $result = $this->mongodb->executeCommand($this->database, $command);3 U+ a2 B, y- s) d. x1 D3 z# _
- $res = $result->toArray();
+ T {( W1 q: L' e3 ?( H' R% \ - $count = 0;
) r9 m: Q+ M0 E c3 @) k3 a9 S - if ($res) {2 u. T) L% R& R: i% c' @% h" w/ S
- $count = $res[0]->n;- n) Q0 B7 M' n/ B+ o9 g
- }
& o, M- K* ^! T4 [7 Q: K$ B+ u) H. t" w
4 D( }; h( \. |$ m, @% C- return $count;
% k+ A2 f6 v2 O# l; K# u; M0 K - }
; A7 ^/ x4 C8 p0 m' k - 8 `4 [2 D- z Y
- public function update($where = [], $update = [], $upsert = false) {
7 p9 R* A" m3 \7 _6 p - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);2 M# r5 B% O" a. h6 ^* Y7 j5 P
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
4 g( R. x* z& e3 m: U2 q' e* ~3 `: S# d
% P' Q1 H+ q" \3 `- return $result->getModifiedCount();
& X7 J+ a( Q* B1 }7 g - }4 x3 d/ Z7 Z# R3 A7 H3 B) J) M
- ) k! K) T. e, n7 h. j
- public function insert($data = []) {9 C2 H6 D+ t. q- f
- $this->bulk->insert($data);: k, N. g5 b( h7 y$ W2 U6 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
$ W( L+ X' p# q: P# Y - 7 _0 y* o" ]% S! R& V
- return $result->getInsertedCount();
3 |7 Z. @. a& z5 ]/ `* j3 S - }) q; R6 t- L( n- {: `3 O' T% K
- ) _9 h( a+ ^" c: s3 E6 X" `
- public function delete($where = [], $limit = 1) {
/ V) p6 [+ Q& k' g* i - $this->bulk->delete($where, ['limit' => $limit]);9 B8 ?+ w9 P( o$ Q# e
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
e! j. H1 U6 |- W# u' E: l - 2 ]3 Z: a. w- }2 Y' U
- return $result->getDeletedCount(); ?" Z6 p2 M7 r# v
- }
$ n6 g# h, M6 x0 [8 E - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新' z2 G* X& R7 e- K6 D; X9 h4 C
2.新增- 原' p! s5 ?! Y k! t/ g. E1 D
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单, |+ a5 j/ t: P( i% F u
- $lastId = $resultOne->getInsertedId();
3 V: i1 D4 R2 J7 z1 ] - $resultMany = $collention->insertMany($array, $options);//多+ U/ a9 ~* _6 `& M' Z
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
" T: Q8 G, v8 ^6 T' H, m! c" [( } - '$set' => $values e' m2 X! O8 ?) W" n& ^
- ,[8 _3 P# D7 m' ~+ S& e& g! ^
- 'multiple' => true//多条,单条false
" j- p6 Z# J0 w) o2 l - ]);
复制代码- $collection->updateOne(, r$ E8 C6 `, i& H) |! U- ?
- ['state' => 'ny'],5 N# S! M5 ~7 |9 D$ q
- ['$set' => ['country' => 'us']]
- I* d/ b" l( P6 i$ V1 _ - );3 X, D. r4 |/ @/ H7 D& H `
- $updateResult = $collection->updateMany($ X( R; F0 X2 j) c: z! h7 u$ w
- ['state' => 'ny'],9 a1 ]- _. s0 K5 _+ W( U
- ['$set' => ['country' => 'us']]
% }6 f: z0 C3 t, M6 U4 h8 G( W+ X1 C - );9 y$ g! E! H# q$ {/ m+ _) x
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原 d4 k3 L& ~: @" o" o0 H. A: Q
- $cursor = $collection->find($condition, [8 W( Q K+ o4 W2 O u
- 'name' => true//指定字段& ]' b) u$ H2 g5 _8 f: |
- ]);; q6 E7 ^( X* Z( K/ s+ A
- $cursor->skip(5);! J( R* V+ n7 H
- $cursor->limit(5);
2 E2 `8 P$ k# h - $cursor->sort([: [* h: ? z# l. f
- 'time' => -1
( R8 ]! i% O6 a$ j3 O0 D9 }; [ - ]);
复制代码- 新
& t( A) ]2 s9 I" v! |8 g
- $cursor = $collection->find($condition, [. F/ Q5 _- d9 n2 ^' n) |) l
- 'skip' => 5,, R- Y4 y: s) V
- 'limit' => 5,
2 ?. g1 {7 ]9 Y) @# s+ L3 i+ x - 'sort' => [. F- q% F/ h1 s/ I
- 'time' => -1
: ?3 ~) h$ q D# s2 N: m - ],//排序3 |, S( V8 M0 E6 `& t6 V5 M
- 'projection' => [
' } [2 F/ ]6 a( [+ w- J+ n - 'name' => 1//指定字段
# h- L$ h1 O) }$ ` a - ]4 N2 n) X% D8 c- f1 b- k* _
- ]);
复制代码 5.删除- $collention->remove($condition, [, k. u5 Q$ h1 {7 h
- 'justOne' => false//删单条
" |7 c& ?/ F0 X* N - ]);- |8 t, B, R T7 ^6 k: h& g m
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
! C8 I$ k8 ^7 {+ { - $collention->deleteMany($condition, $options);; o7 l* S* \- E
; |* L( [3 h0 h& {. b( D, r- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([ A4 c: o* Q! J' g5 R* k; M! v- ^
- '_id' => $tableName//我在自增表中用其它的表名作主键
! |: q$ R2 r5 f2 s& F - ], [: C0 B8 x4 f. q4 i% x. s3 C' b h3 V
- '$inc' => ['id' => 1]//自增
/ ~1 Z( S9 n3 A - ], [9 [9 l5 t7 k3 E1 D `
- '_id' => 0! ?7 e( D' A- A/ [8 k6 R" z1 x
- ], [
! B* s& K. h4 I5 D. O - 'new' => 1//返回修改后的结果,默认是修改前的& a, C& K+ ]% q7 H7 C' U# Z7 d
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
8 c: t9 F4 c& `. k2 {. x - '_id' => $tableName$ F1 G; |3 F$ ?5 \4 G
- ], [
" r) d' a! M3 h - '$inc' => ['id' => 1]1 w) P. D6 O0 ^+ {
- ], [
5 z& S& O$ q: ? U - 'projection' => ['id' => 1],- `% @' C. E4 \& j8 n
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER0 B) z5 h: Y- r) p
- ]);
复制代码
0 v0 x6 X& o6 C7 l" y/ n9 ]4 E) w& X* E
- y1 j8 O% ?6 U% J |