使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
e8 d! C4 o! C# v R. _
! Z" ~6 k* H5 o1 t6 b, Q- use MongoDB\Driver\Manager;. ]4 t. q, r# _& G
- use MongoDB\Driver\BulkWrite;
; O# h. M( } I& p! \ o - use MongoDB\Driver\WriteConcern;! ?( s6 n" P) P- e/ _+ D
- use MongoDB\Driver\Query;
# n0 X% O1 d/ h( w5 i - use MongoDB\Driver\Command;! J! h7 h6 V7 P, R- t: r/ F' N
0 m8 k5 [, z2 y- class MongoDb {6 T. @4 Q8 |' [3 b' c5 e
- k3 h# `! M6 E+ Z# ?$ P9 @- protected $mongodb;
/ r0 J* [3 @, }: C - protected $database;* o( ]4 V I" m% _4 i6 \2 L/ Y
- protected $collection; W3 r( ?0 Q7 P% G* h
- protected $bulk;
" x$ N/ r9 G/ h& p& J4 K! v - protected $writeConcern;3 B6 n4 ~; \* C A) v u
- protected $defaultConfig
' G4 p/ F! _, p4 S - = [
. _' i. T0 p4 K3 f( {$ ^* N - 'hostname' => 'localhost',0 L5 R3 v& D! O5 T0 w' L
- 'port' => '27017',
' X7 B2 F8 i( j \ - 'username' => '',
2 H. i& L1 m2 H% J8 e: I - 'password' => '',8 r1 a, a8 j% l e2 F: \' V
- 'database' => 'test'
8 C( r$ }9 q* m& Q% \ - ];& ]! Z u' m+ k
- V% v* E+ w6 [- public function __construct($config) {
0 X! @, `& \1 O( g: c6 q. } - $config = array_merge($this->defaultConfig, $config);% Z9 N9 W+ n* o" G- K- i
- $mongoServer = "mongodb://";, C' l8 E3 G% g( j
- if ($config['username']) {( B( x' c- J& m" p4 Z5 V
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
# Y3 m, E3 K( \$ j$ W, J - }- Z9 G) @- n. ?0 v
- $mongoServer .= $config['hostname'];
- H! E& B8 h, Q' _ - if ($config['port']) {
, D4 p) e" a# w0 A8 B" _ - $mongoServer .= ':' . $config['port'];+ x, P" I& i7 k8 I2 K: U
- }
& T& k* x8 B* M" d5 Y& d - $mongoServer .= '/' . $config['database']; E1 h5 b6 W3 \3 i* ?
- . b6 X3 o1 N( ?1 J% G7 M
- $this->mongodb = new Manager($mongoServer);
' ]/ z* v. N; O; @3 ]0 | - $this->database = $config['database'];# X6 b6 L z" u b2 a7 k
- $this->collection = $config['collection'];
" E9 K* S/ `/ P4 k - $this->bulk = new BulkWrite();
9 l! A+ [" a3 C* |' z: w U - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
/ p" k% a0 N6 y( h2 Z4 r; B6 _ - }
, Y% H( r/ S1 |/ k' _5 j" Z
5 t$ J4 l4 p# R3 M4 i; L- public function query($where = [], $option = []) {
% X n( k- {4 I! v$ N - $query = new Query($where, $option);7 b. h- \8 V. X7 k
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);$ Z) I! x$ _) J6 h# b
- 5 H, D& C3 t( B
- return json_encode($result);
% T, i- T( ^8 o4 n - }
5 V% G4 x; c: ~5 M - , b' V" h- R* e* `! J! ]' Z' S
- public function count($where = []) {0 y5 @* t; V: P% f6 @
- $command = new Command(['count' => $this->collection, 'query' => $where]);
7 _7 ^0 `2 s" l& u - $result = $this->mongodb->executeCommand($this->database, $command);" i/ X. `& |2 d/ @+ v
- $res = $result->toArray();7 w' I- U h/ Z6 ^+ Q1 n
- $count = 0;: i+ o1 n, D! K% q
- if ($res) {) |7 }) m8 m- \$ j7 s f
- $count = $res[0]->n;
w( C( L# B: C' x5 g - }
7 K. r* W5 z" ^4 k - 2 N: p5 E0 q2 J3 b" F# i
- return $count;; W; w$ ~$ V/ t+ F
- }
" f7 L6 S# ~; W; m4 ?! z. Z+ N, ~
6 u! s0 m8 R2 J1 G! M: o- public function update($where = [], $update = [], $upsert = false) {
8 g7 a4 X* V7 L" J, Q+ d# j6 B9 D - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
" \* p1 ]9 K+ u4 g+ n; ~6 { - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# Y% o# U) o# F' u0 |. l& Z: h
- 5 d$ U+ x9 T# R* t6 N0 e6 ~5 W
- return $result->getModifiedCount();) X/ {7 G! C8 i% j& H) T! Q/ |6 O
- }
& e3 W' ^, W- O2 U: R% Z$ w
3 i. F, W% u7 w( H' p. ^$ E- public function insert($data = []) {9 K* s9 M, o$ G1 H: R8 u& |
- $this->bulk->insert($data);2 R7 A) {8 a& Z6 V( u1 T2 T$ N
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);+ d% I J; @8 K- P2 I# [4 {9 W
0 h F. x% A. q' }- return $result->getInsertedCount();
" a/ l$ Z" a" V) ] - }
' T5 Z& N2 k7 S/ ~/ B - 9 B: G3 ]# o( h! {. e# m
- public function delete($where = [], $limit = 1) {
6 `0 O( J2 l% R. ?5 P% q$ S1 E( r- [ - $this->bulk->delete($where, ['limit' => $limit]);
5 B$ I" c) O; i$ y - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);: u% @: x% M& `+ D) Q: c0 S" _
/ c3 j, w* X8 j* J4 }" f) b; [- return $result->getDeletedCount();
( J \5 D7 r- e: G/ H+ u - }
; R7 A! A+ J# V* x0 }0 J& q - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单
: Z9 e. W/ v$ j/ N8 N3 e/ E6 {! @( l - $lastId = $resultOne->getInsertedId();
. Z7 p) F1 D$ Q9 Q( u' a - $resultMany = $collention->insertMany($array, $options);//多3 u% f" p$ N& e" g; Z/ J, w
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
5 W$ N2 G/ T" q) C% C' }# k5 z
- $collention->update($condition, [
- f2 u* j7 n; a! Z - '$set' => $values. i5 B% K; s- ?- r# V- C/ ~( `8 K
- ,[, X- n; S7 e6 T
- 'multiple' => true//多条,单条false; @. Q; ]$ q1 o1 e
- ]);
复制代码- $collection->updateOne(
# j+ { ]8 B1 @" M - ['state' => 'ny'],% A e* U# f# U
- ['$set' => ['country' => 'us']]& |* ` g! F$ L4 B; l* k
- );( y% O) n8 g8 Z4 X( t
- $updateResult = $collection->updateMany(, v9 ]5 B; ?5 {* H$ H! F
- ['state' => 'ny'],) e: [: `0 ?; c: z
- ['$set' => ['country' => 'us']]7 Q% _5 J2 r1 {8 w' E# z
- );1 H0 f$ m, \$ M! y7 t" {
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
2 e9 p6 w% K0 h! ~6 q5 l: _
- $cursor = $collection->find($condition, [3 T# j9 u. z2 O0 j- n2 U9 |6 l g, f
- 'name' => true//指定字段/ W: Q$ X5 w, N- ?- G
- ]);
5 P; D5 q7 p k9 l! v - $cursor->skip(5);
% K5 x7 M* x6 D' m* ], G - $cursor->limit(5);# |& g! x: G: t2 b
- $cursor->sort([6 e4 [0 B; a( j1 K! S8 L' s2 f
- 'time' => -1
' R- Z, ~7 K; b' i5 A; w1 {0 m# _ - ]);
复制代码- $cursor = $collection->find($condition, [* O) o! w: O4 w3 `! h( z' `/ q
- 'skip' => 5,
/ W, D, \' _9 U' F# u - 'limit' => 5,
# f! q ^# P V; L4 X% ]2 Z - 'sort' => [
- y2 G. b: q5 [' \ - 'time' => -12 P& z" K3 \4 x8 z# Q, ?
- ],//排序6 {& C ?2 P2 P+ p, z
- 'projection' => [
( o% v, v: @- R4 D - 'name' => 1//指定字段6 C1 K7 w# B _: ^ G4 B- S0 ?3 y
- ]6 p W( g& D6 }6 w1 R5 y& }2 o% K5 S
- ]);
复制代码 5.删除- 原# y8 p- u; v8 I# J* q, ~
- $collention->remove($condition, [% |) K& G- P t2 a, J
- 'justOne' => false//删单条
+ n/ F* i1 S2 d& `1 h( A - ]);
' s( f* G* V) e' U% P: O3 W0 O - $collention->remove([]);//删所有
复制代码- 新5 y2 K5 Y$ ? e" D) N# @! m
- $result = $collention->deleteOne($condition, $options);' s( D8 Z1 D1 }" V7 ^5 A
- $collention->deleteMany($condition, $options);
) @- ]6 [: b5 |
; W( r* t5 r, T- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
( o9 g) X$ s. ` z- Q+ q - '_id' => $tableName//我在自增表中用其它的表名作主键
# d! e) ]; w. c - ], [
2 e9 z* i+ V# G- h9 D - '$inc' => ['id' => 1]//自增) y; C8 E1 l% c+ y- g2 r
- ], [
, @9 ^* [; C6 h( v1 r- T3 j+ t - '_id' => 0
& S, k* v) N+ B - ], [
# u! R& ? C2 u- W+ J% j6 M6 h8 } - 'new' => 1//返回修改后的结果,默认是修改前的
" ~& Q$ K3 i( ^4 a$ H7 C; V' e2 { - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
1 v6 l) r* V8 k. |+ k4 w3 s: L - '_id' => $tableName1 `& Q7 H# u- A$ m! W2 J+ m
- ], [. S, z( a; ^+ X2 [% H) x6 F
- '$inc' => ['id' => 1]
A# Z6 G2 |; U6 E5 o - ], [
0 B, w1 R. ?8 h: [# c$ {8 H- W - 'projection' => ['id' => 1],
3 l% Z" P+ q" D" J - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER& r" d5 W0 C- W+ {- l4 {; o4 k2 C
- ]);
复制代码
. S0 ^- d3 R3 z6 m7 s0 W
- U! L* A' ^: R/ G+ W |