|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
9 o' O, T' U2 Z. k/ l
& Q' _$ B* p4 f4 U% s5 g' F- use MongoDB\Driver\Manager;3 A* Y6 T8 P' [9 _( O5 s
- use MongoDB\Driver\BulkWrite;- r! Q9 g" |3 S1 _7 |
- use MongoDB\Driver\WriteConcern;- j0 P' M, s& z, b4 M
- use MongoDB\Driver\Query;
( j6 y& W4 g, W# `2 b* K* Y5 T( ^ - use MongoDB\Driver\Command;
/ V+ \/ j9 f$ @& o7 A R - $ j& B* R+ I5 o0 r, l
- class MongoDb {# q7 @; M4 k" F( }" R7 {- d
- 4 F& c6 h4 l! L) ?2 e
- protected $mongodb;* S" m; p+ x7 r b- ?3 u
- protected $database;2 K1 t# }: Z5 T& u3 f- [
- protected $collection;
8 s, u- s, U1 J - protected $bulk;$ D% U1 B7 \1 A1 K6 w4 P( |
- protected $writeConcern;+ x% h: B; _7 N& o
- protected $defaultConfig" v9 C) |* _% Z
- = [
; Y/ R+ a( s% n. I! M* C% o$ \ - 'hostname' => 'localhost',* q$ J/ E6 w& W; d$ O+ |2 V
- 'port' => '27017',9 p/ y: L m1 S6 U( h7 n- U
- 'username' => '',
: t8 q; u# e' M6 A* ~/ Y- i; W - 'password' => '',( F* k6 G8 o3 d8 l
- 'database' => 'test'- G# v- b/ x5 L" A. F; X( h
- ];9 ^, ]* K+ }! q' i' F: O
" a; x% R* C) M0 v C3 X; M- public function __construct($config) {8 I6 O. O7 b. R) H5 c1 c
- $config = array_merge($this->defaultConfig, $config);
; z; L1 y* C# h4 E. f* M - $mongoServer = "mongodb://";
' }; i* Q0 T4 N5 H - if ($config['username']) {
g1 J0 R$ v4 }1 a# e3 h- D - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';0 f. e, Y) n' v) A8 U- s% P
- }( l9 u' R3 y2 y- u5 Q1 }' X
- $mongoServer .= $config['hostname'];
3 c) y, m1 F" H4 G2 W; M$ m) } - if ($config['port']) {* O" r6 Y8 b' O# e4 v. \
- $mongoServer .= ':' . $config['port'];
: J: @8 E% q1 E1 ^/ H$ y, W; X - }! ]1 s" \. h1 E s
- $mongoServer .= '/' . $config['database'];1 {& b* f/ m. j) _) ^: A. y
- - J5 r$ W# ~) S4 V3 {& j! C5 [
- $this->mongodb = new Manager($mongoServer);
8 g8 P; U: u. B/ C1 i - $this->database = $config['database'];
! i' w6 B% j7 o - $this->collection = $config['collection'];
, I4 s: L4 B% }' V - $this->bulk = new BulkWrite();
& F1 [% u: h& ]- O, z+ ~0 D. _ - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
- G, E6 S. M/ u3 S! R - }. z. s% E# i* N: H3 H) E; c
- , B; b4 v6 @! c% E g
- public function query($where = [], $option = []) { }* c: `( N4 x! a
- $query = new Query($where, $option);
& Y8 c) V9 Z3 d2 E9 C f - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);! Y6 _% D. D$ m# g( @! o
- . l5 r$ \7 k1 d, o
- return json_encode($result);
6 `0 O: k' _ U6 n V# ?7 o* l - }% a0 R0 x, {, Q
% f- K, t$ r) [- E3 t9 W- public function count($where = []) {
! s8 E7 U9 ~, M- L- y0 A - $command = new Command(['count' => $this->collection, 'query' => $where]);
* ~. i' b: x( r0 w; a - $result = $this->mongodb->executeCommand($this->database, $command);
% b; M; ]3 ~8 T. [0 S - $res = $result->toArray();
$ j2 I' y, I1 D3 m/ H - $count = 0;1 `& v, i7 W3 ]' E' p2 M
- if ($res) {* i7 `. n6 l) _( e5 Z. m6 O
- $count = $res[0]->n;+ Y' Q( R5 v: [2 c2 K, U
- }
: Z% ]! e9 z9 y/ P9 \9 W
. k# T, X/ h; o: j3 a- return $count;
1 O+ ~% G/ G: c, Q$ ~- u X4 b - } S/ ?$ z% ]$ }& ]- p# q
- ) e1 W1 O9 |4 R
- public function update($where = [], $update = [], $upsert = false) {. G, g% h% \- Q; m d# t3 [6 z
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
1 B3 T% q+ I$ [+ N: g; a - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
; m' X& W6 c1 H) N, j1 m# J9 m - - ^, n& v1 q' E& J! ?
- return $result->getModifiedCount();
) O) f3 Q2 o0 T* B - }
: @: b- c8 @2 z6 G3 @ - 2 t! R. ^! _" s1 ~ |
- public function insert($data = []) {+ Q5 e) o" l8 ^" W, Z# a: [
- $this->bulk->insert($data);
/ U* n$ Z2 P, L% X' s - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# Y8 e. K$ b" Y) J1 t9 }
- % S3 g( }9 a9 K% R% T
- return $result->getInsertedCount();5 `0 W9 F3 a8 ]5 H
- }# B/ G& x: r: m" \+ F/ s
- g, D: i$ C% [1 {+ z; k( `
- public function delete($where = [], $limit = 1) {
3 z. G5 o' a9 l) j - $this->bulk->delete($where, ['limit' => $limit]);2 c! m K/ W; x
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
" F6 y$ k& A8 S2 o. C! ?( B3 l2 m
: \7 m2 B* X V6 H; _- return $result->getDeletedCount();) O. q; m: d2 z- r7 ]. w: L
- }
" G% k5 B+ [7 b6 R - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- 新
1 l% i! _% c* ?+ X s, o% Q
- $resultOne = $collention->insertOne($array, $options);//单
' }8 y# T& ^, q4 C) } - $lastId = $resultOne->getInsertedId();
3 N0 j0 V6 r& A, E% O# w - $resultMany = $collention->insertMany($array, $options);//多5 j; u' S6 ~- Y/ u8 D
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [- E9 |" ?+ F0 V' s k
- '$set' => $values& I4 g# L* r2 E" {/ d1 P! S: b
- ,[0 P9 ^4 i4 ~9 }5 V n: d
- 'multiple' => true//多条,单条false
# i7 r# X* k$ `7 ^9 G& D+ j - ]);
复制代码- $collection->updateOne(
8 {9 y1 }/ E v6 F0 I* k! v - ['state' => 'ny'],* ?3 D3 ]! Q5 I) C$ [1 Z+ \
- ['$set' => ['country' => 'us']]0 B/ P; ^* {- w: w, l5 d# M
- );& N e; i0 t1 Y& K* G
- $updateResult = $collection->updateMany(0 `0 q# N2 ?# z# b/ Q
- ['state' => 'ny'],: T3 ]$ m' P: Y; X: m; |$ L% H
- ['$set' => ['country' => 'us']]
; w1 |- H. ?. e/ I& h" B - );/ T/ h( V7 Y1 B5 c' S
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [+ m. W* W* Z! X( ^: B0 Q: _
- 'name' => true//指定字段
5 ]; P7 C* ?- V+ Q0 T- V( A - ]);
' N$ j# i- h8 ^5 @8 n - $cursor->skip(5);( {8 h8 v N( P% q
- $cursor->limit(5);
j1 b2 ?! z7 |- m! b1 [ - $cursor->sort([$ @4 _6 T$ u$ U+ c
- 'time' => -1
+ x+ F) H8 I5 x% B+ r - ]);
复制代码- 新
& k, Q2 q" m. O+ }6 w9 g
- $cursor = $collection->find($condition, [' p! s' f" B6 s, g4 ~: a4 E
- 'skip' => 5,/ L( F+ X$ ^6 B
- 'limit' => 5,
. S# e9 V# ^3 i* ~+ } - 'sort' => [
1 ? @; `* K- V! g6 L. y7 A, E - 'time' => -1% K! `7 r! Y# W0 D" q8 u: s% Y
- ],//排序
0 M0 G& B, P5 q8 y5 C - 'projection' => [( p' G s$ E6 i: w5 m2 P# L1 u7 u
- 'name' => 1//指定字段
% u) [, Z' S& Z$ F6 c+ U: u, } - ]; T8 i$ a) p7 T; B4 t. Q F
- ]);
复制代码 5.删除- $collention->remove($condition, [
; u' a4 u1 }) l6 {# n, u - 'justOne' => false//删单条; q% C# p$ [, Z% L `3 z
- ]);7 ~, ^3 v$ Q% ]! q7 Q
- $collention->remove([]);//删所有
复制代码- 新 p9 E6 i4 ^1 s" H" B8 }, ]
- $result = $collention->deleteOne($condition, $options);
/ A* X. J0 u$ ?& B& V - $collention->deleteMany($condition, $options);
6 A2 S t8 ^; r
' w ]2 w1 ]# j E- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
6 g; q1 K/ }* [# f2 J2 P - '_id' => $tableName//我在自增表中用其它的表名作主键6 [% G3 p6 k! ^0 d+ P# ]' D
- ], [+ v; {- L* K9 c- u- p
- '$inc' => ['id' => 1]//自增" `/ V. F/ B* Q2 Q1 Y8 u3 u' j
- ], [
: ~" r8 \3 y5 d" n - '_id' => 0! L! B4 Z0 t( q9 ~( i
- ], [
2 V) J$ T/ E3 @0 y8 {- D" Y: f# F - 'new' => 1//返回修改后的结果,默认是修改前的
( n. G# E4 x# C( x - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
! V- m0 a9 k3 r ~0 u& d/ q, L - '_id' => $tableName
& d! ^& F `# u* ] - ], [/ R6 A e! {$ }& `
- '$inc' => ['id' => 1]. ?8 v2 }! ?, Z6 B& [1 G
- ], [) \8 m- a6 B2 H8 ?/ a0 q! T; |
- 'projection' => ['id' => 1],
! T2 o: r$ L$ \7 y) S, y - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
. k+ y% J9 E% Z. I5 g, S' B W - ]);
复制代码 0 |- n. A' }' j- |" y5 T
: B. C- y9 Y+ b# e( Q- e; N
|