|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
! Y" ] ]& O% |1 ?7 m - ! |2 J' ^. ]/ ~: }
- use MongoDB\Driver\Manager;: m" c7 O! p7 ?
- use MongoDB\Driver\BulkWrite;
6 B" y4 P% B+ a! g3 m7 A9 H - use MongoDB\Driver\WriteConcern;* {: T( O/ L4 C3 d, G( x
- use MongoDB\Driver\Query;
7 f) f3 l+ H5 V5 A. U% T: f2 D - use MongoDB\Driver\Command;
2 S5 ^) q; A- `
7 ?) k9 b2 [* J: E: C& C- class MongoDb {! J) t/ |* m, m" w( z! ~7 y) L" `( J
; M% B; w% R; C' I& {, j- G8 p, o4 J- protected $mongodb;0 b" E. T9 {$ P: i P+ Z( N* z- t& \0 {
- protected $database;! v8 ~6 X' {6 N1 Z1 R9 m
- protected $collection;# [) K4 x. g R0 z- j, r
- protected $bulk;6 G- `: i$ r0 E' I1 ~8 d
- protected $writeConcern;
9 R+ j7 X. I- e+ T# E0 h% T; e ? - protected $defaultConfig
9 u; L" F3 p* @ ~: V5 f! x) F1 w - = [- Z3 T7 M+ u2 k. |
- 'hostname' => 'localhost',
3 \! g+ z5 z0 _6 a6 H - 'port' => '27017',- w. ?9 l, u$ H. @
- 'username' => '',
/ b1 M E. i' G# w/ v# } p - 'password' => '',
4 b% Y/ s! k8 L, l4 M; t - 'database' => 'test'
4 i1 F1 r" G' K# R8 g0 y3 l& ] - ];3 J/ ]8 F, F$ K2 i( u
- % S O2 L3 S# w/ X3 X9 M
- public function __construct($config) {. `) y6 w) t! y# E' T; J7 t
- $config = array_merge($this->defaultConfig, $config);3 `9 h/ ^9 ]( ?1 w
- $mongoServer = "mongodb://";1 h' ]6 F8 |3 |2 y! [: j* U
- if ($config['username']) {
2 d! |3 k- ~5 \3 e5 u2 f - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';, p0 x5 _1 x# b2 a# v
- }3 s* x+ Z( W& U0 ]; l8 Q: g
- $mongoServer .= $config['hostname'];
) N @. \( C8 ]0 }4 l9 D - if ($config['port']) {5 t; {/ I% A2 D/ H. G- W
- $mongoServer .= ':' . $config['port'];
0 v+ r, p6 d+ z" n [$ x% A, u# g - }
. d8 t- O, |" @! k$ S( H8 i' {2 Q - $mongoServer .= '/' . $config['database'];
+ `+ p- v* s X; S9 U
. L9 W, h+ m z+ t- $this->mongodb = new Manager($mongoServer);
a: E1 N" N z) a1 h - $this->database = $config['database'];
5 d. }; x$ x# M/ `3 b" {8 x - $this->collection = $config['collection'];
1 _6 T/ U' `0 ?+ D7 _- X - $this->bulk = new BulkWrite();; K) n/ t9 ]8 i" S
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);& h, F, f: V5 @* R2 U6 c) v& q
- }
, L) @" T. q: f6 d5 Q8 j - ' c+ _: M) R9 r% i- H, G
- public function query($where = [], $option = []) {
* M- S& o# `4 {0 v0 }+ O6 f - $query = new Query($where, $option); K! E' `' N/ A8 X
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);- ^- j$ c, q5 x4 t/ Y# o. u4 T; Q
- 8 \# K9 y, k# |* v4 i
- return json_encode($result);
# {0 k/ f. R7 i5 C0 ~ - } k: _* F6 l6 T! n- z
- 0 d* G5 A; \ ]
- public function count($where = []) {4 }; f6 d/ y" o/ q( i7 j
- $command = new Command(['count' => $this->collection, 'query' => $where]);# V5 @; x$ T8 k0 l
- $result = $this->mongodb->executeCommand($this->database, $command);
4 R ~) L5 H# ^! a% S - $res = $result->toArray();4 h0 g% V h" m0 @* U2 y
- $count = 0;: f1 p% J# z( ]
- if ($res) {
8 Y7 r% J" q) j+ `! y - $count = $res[0]->n;, {$ x% O4 [' X. i6 O6 n: C; e
- }
" f' a( b# n; l: `3 @0 I, V
8 J! F% w0 W" a/ _$ Z }- return $count;
( H: D$ R& P8 t0 @6 t/ W9 M1 o - }
9 p1 N% l9 ^( r+ r - ' | Z* d" |: G2 D/ ?5 }
- public function update($where = [], $update = [], $upsert = false) {
% k) V/ ^" ^. o3 b* ?7 w( V% T* |" K - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);+ S' N3 `4 m. p5 @
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);4 J6 a. Z0 c9 b
4 q$ ?- l# p- G. d. u+ C- return $result->getModifiedCount();: G3 G5 ]9 P: X. C# }$ G
- }, |6 d. f! e6 {& M
- 5 k1 D5 _6 e9 y
- public function insert($data = []) {; z! J( B/ Z! g
- $this->bulk->insert($data);" }( r/ y$ _' h4 D Y8 Y: ~
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);. J5 K8 h, [9 O/ R5 s1 K
& R0 R; }; I# t4 h- return $result->getInsertedCount();
/ G0 n* C" J+ X" o9 W9 o# j - }( B; J4 _1 c' o2 G: d- k8 Q
- . V; V* F; x( N* l" P
- public function delete($where = [], $limit = 1) {: B) h% z6 p$ G4 r8 z+ x+ u" C
- $this->bulk->delete($where, ['limit' => $limit]);
9 M% V) F4 s2 ?; G) q - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
0 T5 C- Z* ]) U, V9 J - % x" @3 i+ \# m; v- P
- return $result->getDeletedCount();
3 l% w. A2 z7 T2 M: e% y- P - }
0 g4 P6 e% o4 T/ T* a- m# Q6 r - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原
% F' ~9 C) y! v6 R& v5 T
- $collention->insert($array, $options);
复制代码- 新 r5 \8 ]) X& `/ i5 j& H2 H
- $resultOne = $collention->insertOne($array, $options);//单
; C" ]: M6 B8 B( F& V: x! b, p- C - $lastId = $resultOne->getInsertedId();
9 u1 i$ R' u( i4 Y - $resultMany = $collention->insertMany($array, $options);//多
) T0 H# c) |2 u - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原' X0 B/ J2 e) `. i& M" d
- $collention->update($condition, [
# _; i) N' [0 A) [( s1 F$ b - '$set' => $values/ H! c. z- M; N# l% Y& j
- ,[. [ r* I6 _7 g4 c2 l* _* W
- 'multiple' => true//多条,单条false$ g: j) |" [; P
- ]);
复制代码- $collection->updateOne(& s2 K; b' }: g2 {9 d& X. Y6 t
- ['state' => 'ny'],! R8 L, O) ]! o
- ['$set' => ['country' => 'us']]2 ]' M& ]2 q. `
- );1 X) Q; ~1 Q2 {, t5 J$ X- w
- $updateResult = $collection->updateMany(
U6 @6 l$ F" W: C- Y ?, b - ['state' => 'ny'],. m E; W* A0 u, X# I N
- ['$set' => ['country' => 'us']]* |; D1 e* `) G0 M' z' c2 |2 ]
- );) d1 r- n% S/ U( l1 y; i
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原% d% d2 N! O9 s* N. |9 {
- $cursor = $collection->find($condition, [! z1 N) G! A* w7 c% L% F; R
- 'name' => true//指定字段: b% y$ O- i2 `/ ^: `, \9 Z
- ]);
/ ~/ N. B% U3 F4 G$ B - $cursor->skip(5);
3 ~4 e3 |! N$ H5 Q" C - $cursor->limit(5);
, F4 K3 {8 K' |' p; I* G - $cursor->sort([+ n0 v0 C. D! T! V7 c
- 'time' => -14 K6 T6 U) B# |9 Z1 b2 z
- ]);
复制代码- $cursor = $collection->find($condition, [" F$ h4 Y* a! ^% K8 u; G0 w
- 'skip' => 5,
/ {# i, U* S+ g1 W& N - 'limit' => 5,
, q0 C; s# F* O( b0 j9 l - 'sort' => [% f) s& Y% e. i. k' C* ]
- 'time' => -1- a1 N4 j# i$ g
- ],//排序
2 L/ N9 o3 B# {3 p F" z' j - 'projection' => [' I+ J/ x7 N: } |
- 'name' => 1//指定字段. H; j; f) g7 u+ c1 D; } p+ T
- ]: i7 m- {" @ s
- ]);
复制代码 5.删除- $collention->remove($condition, [5 k1 J( U& j# | Y y$ `8 H2 I- F
- 'justOne' => false//删单条( B0 z4 o1 l; F7 K( K6 |
- ]);% @; \" }3 Q5 w; h7 b8 {+ y
- $collention->remove([]);//删所有
复制代码- 新9 R* [" t# U2 R7 a% |" R% q+ b
- $result = $collention->deleteOne($condition, $options);( q+ Z9 w0 O- c' {4 c* |3 u; h7 s
- $collention->deleteMany($condition, $options);. [' ?6 S0 d" i' `( g3 v6 m
3 P, c& \& c; }. U) T7 k- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([0 W8 Y+ D J" n7 R9 k" n# e
- '_id' => $tableName//我在自增表中用其它的表名作主键
1 e2 u/ E d: a9 q7 A! P+ L' C - ], [" s! q2 O/ V, V8 d3 U0 u
- '$inc' => ['id' => 1]//自增
8 z# p) a9 p; L* O - ], [
1 s. X" l; w3 }+ z* L6 a5 X# L - '_id' => 0
1 m( T* l+ N# j% r7 S4 F9 |1 O - ], [
* ]1 o' c" u. E7 Q S# B' V& [ V - 'new' => 1//返回修改后的结果,默认是修改前的
. q" W) x! J" G0 w - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
6 X, O1 D- L) q4 r - '_id' => $tableName* ?' `* n) C; `: T( ~, w
- ], [
* N1 K3 D7 F1 o: I. X* L - '$inc' => ['id' => 1]6 O4 \$ ^; h2 E2 c) L+ K1 p
- ], [ x+ @5 y( x& @' L
- 'projection' => ['id' => 1],9 ]7 \2 i7 T4 X* i; j5 U' T
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER/ G% w8 s0 I- q9 B
- ]);
复制代码
0 l6 B% {& A) s, I
/ S1 i: Q# o' v- h |