|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
( g' S u! m. p6 o+ B& }
) ^! T' y5 ~6 x# `) A- M2 |- use MongoDB\Driver\Manager;
4 i! ]1 f8 x$ T, H9 k - use MongoDB\Driver\BulkWrite;) o0 a, I4 n l
- use MongoDB\Driver\WriteConcern;- d' j9 E! {5 _% v9 b' W3 Z$ C; U
- use MongoDB\Driver\Query;
9 C) a- k$ E/ L$ l; m% G - use MongoDB\Driver\Command;$ d& I# F+ E8 P9 G. l
' U' m [, }; x! O2 ?- class MongoDb {8 |+ |! ]# S8 x5 O+ J
- ) E3 Q7 X( |! E: \# b) E
- protected $mongodb;
7 _4 l: g7 |" H" M _) f R( D1 v2 D - protected $database;. O: H+ h6 L2 P1 D
- protected $collection;$ L- q1 W* N `* o7 }# h
- protected $bulk;5 w* ?5 n' F# @4 _( i1 [, l
- protected $writeConcern;
- E" m/ b% w: ]8 B - protected $defaultConfig5 _/ @6 h1 J2 r
- = [
$ Q8 n: P9 \' g - 'hostname' => 'localhost',; m9 I4 i- I2 Q8 `3 S6 X
- 'port' => '27017',
7 ?* J1 C( n* ^ n2 ]$ B - 'username' => '',
& i1 |3 \$ {' E9 {6 w5 }, T' ] - 'password' => '',
6 M5 I& v0 i( o( b% m - 'database' => 'test'& X7 h2 R9 Y$ S# ~# f
- ];
# `( O) k4 z$ L2 l6 j% I# \& f - ; Y& T M$ R. i2 |. J
- public function __construct($config) {7 p0 v) ~3 A4 `( v4 y
- $config = array_merge($this->defaultConfig, $config);( g% Z+ P$ L. \( D& H
- $mongoServer = "mongodb://";+ R# L! P, V1 O3 ~
- if ($config['username']) {
9 s& W' o5 S: {8 ]. D* u2 ~8 q/ P - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';5 \" T6 N8 O3 N i5 _# }" P- s
- }
8 z- p- x e6 @, { - $mongoServer .= $config['hostname'];
- Q* f6 \7 [8 R$ g6 ` - if ($config['port']) {
6 D% G5 V! t& I+ R! D3 F* {2 q - $mongoServer .= ':' . $config['port'];5 J% ^- d' T) e7 R
- }
4 u& W, T' L4 ^ - $mongoServer .= '/' . $config['database'];
, U/ f! B2 Q1 y& i" M6 @! k# l - : y7 y9 C3 z3 t1 B4 L4 C2 p, ?1 i
- $this->mongodb = new Manager($mongoServer);
; c, U) d* Q3 u, t$ \# B - $this->database = $config['database'];
% P4 t7 ^" j: _( ?7 f2 z - $this->collection = $config['collection'];
/ D& W- Z. x# L, `! P3 b - $this->bulk = new BulkWrite();1 D, Y/ y6 q7 @9 B8 Q* K8 Y
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);: u" P4 @# y- A; ?, V
- }
1 t; V! Y/ K' [ [' l
% T- \- T5 S( [8 X$ k( a8 @4 z- public function query($where = [], $option = []) {
2 C! K5 X8 [4 u- `' s - $query = new Query($where, $option);
5 R3 n' e+ z( c+ }0 `! ? - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
1 `: }# `% a- {# W - # W G1 Y6 Z( L0 ] i+ s: g3 r3 V& R
- return json_encode($result);
& F9 i6 ^* @, h2 \9 |7 q. r5 k. n5 b - }
, ^! G* a. k, Q3 ?: J$ L# J: I; f9 h& L
& `4 F/ M! D) a- public function count($where = []) {3 e7 {3 L; r0 [# ~4 x
- $command = new Command(['count' => $this->collection, 'query' => $where]);" \5 v7 V% m8 E0 U) l p
- $result = $this->mongodb->executeCommand($this->database, $command);
$ H% x3 a5 s; I# a3 P - $res = $result->toArray();- m$ P8 Q1 x' s* t
- $count = 0;
9 x H# W! c# R7 j5 k - if ($res) {: S) e3 ?. q6 _% Q; i7 I
- $count = $res[0]->n;* S: d$ c2 L- {7 R% S! X7 f+ {" w
- }
% U4 r7 f( q( M4 Q - - y ]/ c) M7 k; [2 A/ J% \
- return $count;
' x9 R U' g( Q$ j( p7 e - } C Q7 t4 @* m( x4 j
) x3 [- G9 o/ L5 m( ]- public function update($where = [], $update = [], $upsert = false) {" C$ Z, P2 L/ _' [+ m2 u
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);1 b4 ]- S6 z) x* d i% T6 M! R, j
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);0 }% \4 b( F8 z. p/ ]# e' I8 p4 W
v. @ Z- Z6 ~% d1 O k1 q- return $result->getModifiedCount();
3 ~4 j+ h v# d! b- d- p/ j - }
% D ]2 |/ l2 m9 i0 w. l( }# \; X - 1 Y B# k- K3 Z, t5 J ^3 R
- public function insert($data = []) {
8 m _/ r# E+ | - $this->bulk->insert($data);3 [" V2 p% Y0 o
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
y& P; Z, i7 f2 p# h* k - + u3 z+ k, T: s/ I$ O; o4 d
- return $result->getInsertedCount();4 A# Z0 T Z4 M- T' o' |- ?
- } g; s. G9 @7 Z% Z" F
- " E' ^2 ], F R$ w* s
- public function delete($where = [], $limit = 1) {# U$ n1 K( h' o; }" ~
- $this->bulk->delete($where, ['limit' => $limit]);0 E4 ?' J6 b( {* J9 F
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);% E- U; G7 R! p+ X" I# m
- ) G3 j9 e2 m; {% a. M4 Q5 U, W
- return $result->getDeletedCount();( p% J% q5 `7 E: x! N v# r
- }9 x' O! G8 @8 Y9 E6 C8 ?
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原, G, z. \, Y/ U8 s. h3 e# h
- $collention->insert($array, $options);
复制代码- 新! U# s* v: B. |7 K1 j! Q
- $resultOne = $collention->insertOne($array, $options);//单
# x0 t+ l- U5 s' U# \) v% _! s - $lastId = $resultOne->getInsertedId();
* D, |- s9 I" s$ P - $resultMany = $collention->insertMany($array, $options);//多% z% X* G' L1 ^* Q( ^+ ]
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [6 Y$ w- p- g/ H
- '$set' => $values; ~1 V7 n: t/ M3 a
- ,[
. b) V, H5 Q" y - 'multiple' => true//多条,单条false, ]/ c" ]# S, {3 {9 j$ e5 e$ L
- ]);
复制代码- 新
- ]+ f# S1 f" A P" [( H% ?
- $collection->updateOne(
2 T& R( {2 e, x1 K - ['state' => 'ny'],- N9 Q( o- t1 v. _" P/ V
- ['$set' => ['country' => 'us']] _5 G2 b. K* P
- );6 M8 t# ?( B7 O; @
- $updateResult = $collection->updateMany(6 x: v" L, K6 h' W
- ['state' => 'ny'],
, Q" C3 |& o' O, {3 G - ['$set' => ['country' => 'us']]5 a9 l% s; O) }/ G" L
- );
2 T9 C; b+ s0 S: K0 I8 S2 g, N+ a - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
& q* H$ D, x |9 P" B - 'name' => true//指定字段
* e9 P; Q4 S5 o6 L5 P! C8 { - ]);2 b$ `! H: B, }$ U8 V
- $cursor->skip(5);
1 G# D* d0 T( o; k# ?( ? - $cursor->limit(5);
4 Y4 o) P' R( U - $cursor->sort([' p0 r, n" {% P
- 'time' => -1
% m( [$ T- w: z) B: T - ]);
复制代码- $cursor = $collection->find($condition, [
4 ^1 U) Q! e5 g - 'skip' => 5,% g, M4 k5 U# U: L1 S1 L
- 'limit' => 5,+ Y& ^6 A' k% S6 p8 h
- 'sort' => [" y' H: H' @4 H4 e2 n$ J9 q
- 'time' => -1& j! S+ s' `6 @5 k" E$ `: c
- ],//排序- L$ ~) {7 f% [" A! e, O- Q
- 'projection' => [
0 D: I5 Q/ R- I: w8 }' Z/ u - 'name' => 1//指定字段
$ d6 M2 A1 b2 ^+ W% a - ]
5 w1 i" b2 N- b. j3 m - ]);
复制代码 5.删除- $collention->remove($condition, [
6 D) d5 ?' \2 j. l! V - 'justOne' => false//删单条$ y: `- k1 A) d% E8 }* A1 o
- ]);$ K% O5 q/ L1 _* T7 L( S! I
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);+ x3 u' G- m% D$ h
- $collention->deleteMany($condition, $options);
# Q7 Z- W$ C" Y' j" |7 D ~
2 @2 I& a9 S% ^0 L- R- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([, {; P; f% ]0 ]) a9 e$ q
- '_id' => $tableName//我在自增表中用其它的表名作主键% K8 t7 u: o" S/ C5 @% |3 T) Y
- ], [; @0 ^2 A. Q7 }2 X, f) h4 {
- '$inc' => ['id' => 1]//自增
/ T1 h( x5 F, n - ], [. a' ^8 v! I' U, F* C& m/ B
- '_id' => 00 Q7 T! j$ Q: E' f1 o8 ^$ ]9 X
- ], [
1 E* E q6 @- X5 F9 b; e* n2 B - 'new' => 1//返回修改后的结果,默认是修改前的
7 {. H6 P; r. ~# D, Z5 z - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([% y! j, o7 Q5 Z& [# S k# K/ @
- '_id' => $tableName6 F8 C! k9 B* g& v
- ], [
( [ Z5 e# d0 k, u- \7 c - '$inc' => ['id' => 1]( K/ F3 M# j7 ?2 g% g
- ], [( m) D! W1 U n1 R( A* Y
- 'projection' => ['id' => 1],# I/ Z' ~) Q: W3 p
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER3 N. [1 x# C3 I1 s1 X
- ]);
复制代码 6 \, K6 r; t( g6 z o D
, r: e3 x2 {, p: x |