|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
$ k7 x& H" n7 s+ } - , q* s& Q! U. u2 Q) Q
- use MongoDB\Driver\Manager;2 C/ Q/ X9 b( Z7 ]- P4 V: ` R
- use MongoDB\Driver\BulkWrite;
& s# w( i6 v0 P9 t0 D. b" E$ G6 } - use MongoDB\Driver\WriteConcern;
) H% s- N* ~& C' l6 {. p6 ^ - use MongoDB\Driver\Query;
7 S2 Y- H( N0 q c. C - use MongoDB\Driver\Command;, H/ t, f0 v2 B6 M" C8 g. M
- 3 ]6 K& N# O* Z9 P+ y& g' F ~# \; o
- class MongoDb {
0 A& R" n( i3 u6 O4 z - ' R0 V: v# p3 E) y
- protected $mongodb;
' W0 M; J! P. I+ V2 Y; c3 }2 _ - protected $database;
: ] P8 {& V/ l$ V+ } - protected $collection;
% y& x3 _5 I, Q$ y6 [ - protected $bulk;
' f w$ V. O8 d9 N - protected $writeConcern;
( x7 z" @/ o1 y5 e - protected $defaultConfig) w+ @ d, ^9 Y. k6 i
- = [
- ~9 Q9 R8 u* _ - 'hostname' => 'localhost', v+ f2 N( B; Y d; S$ ?- I
- 'port' => '27017', W; E5 {9 A/ c
- 'username' => '',
0 b. V1 M8 B# @$ `' F0 x7 O4 G1 k( G - 'password' => '',* O5 y1 k! S6 |5 X
- 'database' => 'test'" z5 s1 T: @. s9 k. h E+ y
- ];( d9 W: G, I- d& I# d) s
- % y+ q+ c, P9 Y! i7 B3 |" u
- public function __construct($config) {4 {- h; N; T# Q) O4 r7 J' I
- $config = array_merge($this->defaultConfig, $config);
/ F2 _# Z1 E+ U$ d! M - $mongoServer = "mongodb://";4 A( f2 J' Y: H2 x& \ P) H$ F
- if ($config['username']) {9 A+ b; N/ r4 z: g( o
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
# e# ]2 _# b$ g7 g - }: U9 g! e) K! ?
- $mongoServer .= $config['hostname'];; x% \1 T# k* R9 F
- if ($config['port']) {+ ^1 S) U! |3 o4 v) \5 e
- $mongoServer .= ':' . $config['port'];
9 K, @+ J( K/ ^' U3 ~1 h/ P3 o( N - }
" f. ]4 z' v7 l8 E: i6 V* w - $mongoServer .= '/' . $config['database'];4 F" I: w4 l, X3 a2 x+ B
) G/ {( x3 a$ A8 h% `/ ]4 o' [- $this->mongodb = new Manager($mongoServer);
* n5 f" q* B% t1 | - $this->database = $config['database'];
/ h& Q5 S, D/ ?2 U) K; @ - $this->collection = $config['collection'];2 M: v9 T' l! _9 K/ n3 t
- $this->bulk = new BulkWrite();
* X6 u g* i3 ^0 w# o - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);; O0 a: D- g1 T6 X# U: \7 v4 K
- }
5 G& C% q: b1 U/ k - & E# E2 W1 }6 X# }* d. s d
- public function query($where = [], $option = []) {
* K$ h ]) q0 ^ - $query = new Query($where, $option);- O( E7 u: M" q! d5 \; Z& G
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
/ j4 [5 r8 `" S0 g; z8 M$ V - , p. {) l6 l: V' M# _
- return json_encode($result);7 a+ k! e( }' p7 t; m0 \
- }$ q F" }4 W7 o3 G* g1 Y
- u2 d( g+ l, n1 W1 r, F! q2 K4 o/ E
- public function count($where = []) {
5 _5 C% Z2 E% Y4 ]: e - $command = new Command(['count' => $this->collection, 'query' => $where]);
, v" U- V1 }% K5 L/ p2 d3 G$ m5 x - $result = $this->mongodb->executeCommand($this->database, $command);* h. b! U6 J) \2 n
- $res = $result->toArray();
8 Y& q3 N$ k. C0 P - $count = 0;; u; C4 ^' N0 n0 y% W, r7 i
- if ($res) {- A3 ~/ F! |3 v4 |) I
- $count = $res[0]->n;
5 _. q% @4 D- U, ?5 x - }
. E, f- q5 O) ^& v - + Z' m( | x; M8 B. s6 b
- return $count;6 B1 l9 _/ D+ m2 n. A- j8 `7 N# l
- }
. ]+ J1 ^: X2 X+ o. g) D8 y! F
0 q" \; @8 L8 ^+ M$ B- public function update($where = [], $update = [], $upsert = false) {
) t1 }, r+ k( {* d& S- ^" N+ @ - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
2 M4 z: e- w8 i- \( Y1 d# P - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);9 a5 m1 @( f T% ?
- ' f/ P R8 d* [- m
- return $result->getModifiedCount();
* X+ d$ t B+ p, n: Y6 E3 m - }/ n, h: X# O7 I/ R; O; B1 K) z- M
- $ ^7 f" p! X1 h
- public function insert($data = []) {
- g7 B4 M0 y3 Y5 x3 l3 b* F. G$ { - $this->bulk->insert($data);) i* m6 w f3 z2 y
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
- P/ ]$ {! @0 ] T7 O* j$ U - % N; Q% Q2 s0 ]2 N8 V+ _
- return $result->getInsertedCount();
- x/ R' ~- u: B4 S - }) V. J6 X: R2 u# M0 I
- # y1 E4 a3 J; X% ^4 H- d% [9 s
- public function delete($where = [], $limit = 1) {+ C$ ~4 J/ S: A2 m0 ~5 z! |0 s% t
- $this->bulk->delete($where, ['limit' => $limit]);4 i: n; V2 A Y4 F, O- _
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);: e( y+ B0 P l! r2 A% B" K" y5 g* B
+ d1 t; |/ f4 m- return $result->getDeletedCount();
" K6 {7 \ X7 E, |. g Q* T - }9 D! l" u/ {$ Q- o" T
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原
3 T8 ^. m* F+ I* N( P) R! Y' e" ^
- 新
- l, P% ~3 g- N* M* G/ \ 2.新增- 原- B6 J! h. r$ C# ~! B- H
- $collention->insert($array, $options);
复制代码- 新
( A. _4 K1 a) b7 Y/ i2 n4 P, A {/ b
- $resultOne = $collention->insertOne($array, $options);//单5 |& O4 U% u( p, @/ u
- $lastId = $resultOne->getInsertedId();
8 m8 y7 m6 H1 f2 y$ a - $resultMany = $collention->insertMany($array, $options);//多
/ A6 Y0 X$ M2 U, m2 C, C6 T - $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
, g5 j2 L$ U) `9 W/ i, v - '$set' => $values
/ \: Q3 v2 B Q. A! z! B3 z! z1 v - ,[
; X. M6 N( r9 F6 ?8 c5 d8 X# h( _ - 'multiple' => true//多条,单条false
% i+ L" x3 o b5 `. U% k) B. \, @( } - ]);
复制代码- $collection->updateOne(
* R8 x* l( c: l) j v; ] - ['state' => 'ny'],
' O2 v! f$ c4 j - ['$set' => ['country' => 'us']]
* Y f' x0 X5 x$ \ - );
% E0 a! T+ ~: e' O - $updateResult = $collection->updateMany(; w# S% p4 D; j+ s' \% d: N2 r
- ['state' => 'ny'],8 s7 B! Y" y+ E `) W
- ['$set' => ['country' => 'us']]
m b/ {1 c% q5 _6 N. q8 g7 n2 ] - );
3 w- V5 g0 e& g8 ?6 X+ M' e& x - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [1 p5 D: W: J4 N4 _0 K3 o) I8 Z3 J
- 'name' => true//指定字段6 ^4 O2 o. d: x7 `& s( R
- ]);
9 G& u+ N) f- T* a: ^$ K3 L - $cursor->skip(5);
! X7 i) v: Y; K: C - $cursor->limit(5);
0 E+ R% @; H; y/ r* ^4 I - $cursor->sort([& r" c/ o6 k+ Z1 u& Y$ v
- 'time' => -1
: h. n; ~2 S; I8 @. h - ]);
复制代码- $cursor = $collection->find($condition, [" M3 U5 ~6 N) }& W5 l* ~% t! M
- 'skip' => 5,% y3 T2 @) }# t
- 'limit' => 5,
) {- A7 P4 I3 ^; M2 d0 [/ B: ~ - 'sort' => [
6 k) o! s! l4 v' T+ T - 'time' => -17 u3 y' G0 a# z" `, G$ U
- ],//排序
+ l6 A* z7 p% x; N6 |+ {6 F- } - 'projection' => [1 c) }8 I* r7 O" U( Q7 c6 a
- 'name' => 1//指定字段
- |- I/ z7 p( v* ~0 }3 R9 J - ]
6 ] W! l; a7 o8 N+ x% `- I - ]);
复制代码 5.删除- $collention->remove($condition, [
" i( a2 c" u2 \5 Y$ v& B: I: [ - 'justOne' => false//删单条
9 v# y9 R; m. o9 W& @ - ]);
) C( A7 G, U& v" Q - $collention->remove([]);//删所有
复制代码- 新1 v2 ` s; q' m% y( y# ]1 X( A
- $result = $collention->deleteOne($condition, $options);+ | v/ }5 o' x: x1 e9 y
- $collention->deleteMany($condition, $options);
: ?" u0 l1 n6 `3 I6 } - - b3 B0 R+ g) x: w0 I
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
+ [2 r# `# N9 R% G" J2 j5 | - '_id' => $tableName//我在自增表中用其它的表名作主键% ^" ]$ t+ R' `# n! D a1 _
- ], [ r) v, p" Y+ m
- '$inc' => ['id' => 1]//自增
! a. ^! v' M3 l' K9 h. q! m& a - ], [
5 ]& p3 y2 c0 k( T* ^3 q, s# I& e- a - '_id' => 0; a; t1 W& e/ J" Q, z
- ], [
5 s2 h6 J$ w9 l! _3 J s - 'new' => 1//返回修改后的结果,默认是修改前的2 c" n" p) H% f7 h
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([6 X! D# `5 L) k4 `4 T
- '_id' => $tableName! k6 a: l# @; M/ k1 C% I
- ], [
3 z! k, u2 M, W" g( e - '$inc' => ['id' => 1]. n" L/ A4 q; s2 B
- ], [
, P3 Q M2 v* ]* F9 @+ N5 K - 'projection' => ['id' => 1],$ D2 b2 l, w( F7 g+ l
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER. U# Y7 V5 {7 D H! E
- ]);
复制代码 4 v a- ?4 K5 o4 @# S
% e+ ?% P9 O9 s, {% o
|