使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
; [8 M4 R) r7 M% X6 Y6 ~ - # z- }7 O) U# y& d
- use MongoDB\Driver\Manager;" P, v; w, u3 j
- use MongoDB\Driver\BulkWrite;) U' f$ Y" Y' G5 L$ U1 R# c* O) S& O
- use MongoDB\Driver\WriteConcern;: {& A5 I {3 x$ m
- use MongoDB\Driver\Query;
5 r% d9 g8 N" Z1 D( V6 Z/ P - use MongoDB\Driver\Command;
& Y+ T& G8 W8 ]% n
- N: r$ [9 Z" s5 ~2 l- class MongoDb {6 j2 x0 e' v) g+ `" @
: J" _+ O7 F& N: A9 b) |7 O- protected $mongodb;
2 G" S) n( s1 C9 W! w0 `9 N - protected $database;) w8 m9 |' y) l3 v1 V1 M: l
- protected $collection;
* N9 O5 m, ]. V7 R) M - protected $bulk;& u+ y8 u% ?/ D/ A8 B- j. Z
- protected $writeConcern;
) D( X9 J# F/ r w2 [" ` - protected $defaultConfig& Z0 H3 a/ w( D7 l" D* P
- = [8 |' @/ B) f, V- I. L# Z( x
- 'hostname' => 'localhost',5 R# u! h, {& |: n8 o! W3 K
- 'port' => '27017',
( y- F: M3 K1 |0 S3 L( ], p. } - 'username' => '',6 `' Z# i `+ n+ v
- 'password' => '',
E1 ^* o% v! } - 'database' => 'test'
6 y4 J. J0 }2 I2 a - ];8 A/ b8 N9 _6 [# g' S9 q8 f
- 9 S* B, n7 y+ s$ h `4 X3 ]
- public function __construct($config) {
& }) N: I. i; I$ n! X! {3 N$ t - $config = array_merge($this->defaultConfig, $config);9 ]3 J5 o$ t" z2 W) n
- $mongoServer = "mongodb://";
% o N: r' ~ E+ M6 W - if ($config['username']) {
1 J# g5 M: ` s: {4 T( S - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
5 v" S; c; J! C7 m. \; V - }4 o, f: D0 u& s' i- b
- $mongoServer .= $config['hostname'];# D$ F. n8 V4 W$ p2 h% |5 m
- if ($config['port']) {
2 z2 G: k5 y4 [, l( a - $mongoServer .= ':' . $config['port'];! b, }1 F+ l) b7 G
- }" [ g, ~! J* ~1 ]5 x; F1 g9 [
- $mongoServer .= '/' . $config['database'];- _& k) v' m; Y2 p/ Z+ I
- % W4 g5 v; S( a+ x$ e
- $this->mongodb = new Manager($mongoServer);2 ~6 o+ h9 Z& F/ ?% ?, t
- $this->database = $config['database'];
7 o! Y+ p2 N$ w& n1 E4 Y+ v/ H+ y - $this->collection = $config['collection'];2 w4 c4 g; q7 y' ~1 ~
- $this->bulk = new BulkWrite();
! y9 X6 U$ H2 v% X" P - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
% H* l* Q- l$ S$ ` - }
1 l# k4 [/ }1 S/ t - * B, s y, N6 [% \
- public function query($where = [], $option = []) {
; E* L" I2 j- \& K7 L - $query = new Query($where, $option); ^0 f3 |$ M: r! D s, \) J
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
/ L& R5 K i9 [5 `
2 |( G3 A! d# u Z4 u) \- return json_encode($result);
4 C5 z' ~( W U* w: e, ] - }
( l4 `) s1 h4 ]& y# Q - & D' u$ }. }9 P9 z: ]$ K& _
- public function count($where = []) {6 T- X% L9 |# m% p9 z$ }1 V* U
- $command = new Command(['count' => $this->collection, 'query' => $where]);0 ^$ K; W8 z }$ B2 _
- $result = $this->mongodb->executeCommand($this->database, $command);' B* ?: H0 \1 Y. H* W9 ?
- $res = $result->toArray();& j: H# @; q9 _
- $count = 0;! d( K8 e* Q& E' L: @* O1 h
- if ($res) {& D7 X( |* o9 G P& E1 _1 U2 \
- $count = $res[0]->n;
; G$ K. m N* a" t( h - }
, i; t3 y9 ~+ U6 _9 j
6 R( R( g) q2 _9 P/ H7 \- return $count;
+ V1 O$ f" b5 g z* l8 d - }( K/ p0 U: \; ~9 k5 M1 E/ B1 A, y. }5 L+ C
- 6 H- O9 p3 L# Y2 {& X
- public function update($where = [], $update = [], $upsert = false) { ^7 }" Q: U1 N
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);$ E- ?" }9 J, y* G& u% h3 W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);/ {: Q* `: ^+ {' d
- / X l% x- A/ y) ^3 S1 B6 G1 N3 o2 ^
- return $result->getModifiedCount();
# I- \- g! _7 S2 o - }$ J, f& x5 Z9 d' h( S
- 1 u0 N( O9 ]" C7 Q# Y8 _
- public function insert($data = []) {. S, V- j r/ o, Q
- $this->bulk->insert($data);. `0 H- L- \6 g4 i5 ]
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 v$ a0 C( e3 D% }- @6 c( J
- |- T5 z' k. |, k- return $result->getInsertedCount();
. R; v3 y" {" z3 x. y - }
- `+ w! Y2 h5 ?- @6 A+ _* p - % d% ~( _8 O: p; b
- public function delete($where = [], $limit = 1) {
1 O! |3 p2 Q* I/ b4 z/ ? - $this->bulk->delete($where, ['limit' => $limit]);) c1 o( l$ N5 N1 y+ V& ?
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
# Y7 w( F" h! r5 ?' [; J
( }8 P' G2 p# Y8 X/ O" N8 Q- return $result->getDeletedCount();
% h5 R3 d2 p" q* L& J' W2 m! Q - }
( q5 G8 J# d4 R8 B, B/ {/ W - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原& c1 r6 v! e1 h# d' d0 _2 I& V
- 新* F$ [( W: @# \+ `; Q ^, o% t# v
2.新增- $collention->insert($array, $options);
复制代码- 新
4 M+ z; h( H- w- Z( } k
- $resultOne = $collention->insertOne($array, $options);//单
) m, r$ ?* z: ~" z8 i7 V. W- O - $lastId = $resultOne->getInsertedId();6 Q0 W, d1 q2 U- s# x9 A
- $resultMany = $collention->insertMany($array, $options);//多( M0 ^2 I3 i! F7 \ D2 W, m0 z
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原* z% F' W9 Z- F8 s1 `; [- R
- $collention->update($condition, [
9 f& I2 y+ ]( l! Z4 S7 Z2 W# C - '$set' => $values2 Y9 [+ R- f1 E' F! h
- ,[& E" \6 m ^3 W& V
- 'multiple' => true//多条,单条false
" f- \+ U5 R9 |8 k# J" k - ]);
复制代码- 新) c4 p& x% ]) T0 D% R0 P+ W
- $collection->updateOne(
* c& i, @# w, ]+ A8 p1 M+ \ - ['state' => 'ny'],
: J/ o8 S3 _/ H! h - ['$set' => ['country' => 'us']]
/ Q) \& d5 E: Z - );
; s. K1 y5 o1 F3 N+ h2 q7 Q! X: @ - $updateResult = $collection->updateMany(! M) c1 V% y$ q4 J9 n
- ['state' => 'ny'],
+ ` J% t; Y7 d - ['$set' => ['country' => 'us']]+ ~8 B9 @$ H- a+ ]* S q6 a
- );0 ]( d( i7 o- T, x$ _% I
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [
1 M) |+ U. U/ x9 K0 A - 'name' => true//指定字段: W. C0 u8 D1 F$ ~* r' W
- ]);
8 g: ~7 x/ J( h0 h6 V - $cursor->skip(5);, n& x$ P2 d R; u9 b0 R
- $cursor->limit(5);& ?9 a# g. P! B9 ?
- $cursor->sort([# w/ ~6 q: y6 Y, @$ A
- 'time' => -1
; v- \/ u* o2 r7 u - ]);
复制代码- $cursor = $collection->find($condition, [
$ C3 E7 a# }6 J& b; }/ b - 'skip' => 5,
6 C9 T! B' C. f6 w9 I& v' T - 'limit' => 5,/ z6 }% M% J% |) Y5 w2 Z) ^ u/ D
- 'sort' => [
9 {# O( M T& K( |) ? - 'time' => -16 ~% @9 |/ `5 p B
- ],//排序
1 e& q6 T! u& X - 'projection' => [* ~* |$ f1 q+ I$ n4 W
- 'name' => 1//指定字段# H6 y+ _: D- Q# |4 o3 r
- ]
" w. Z' e, t9 h- U8 _4 p - ]);
复制代码 5.删除- 原
/ K8 ~$ m8 u0 r# E0 g; d
- $collention->remove($condition, [
* ]3 ]4 u( _ P6 c! ` - 'justOne' => false//删单条* V% A1 J# U' w
- ]);
" p; V( B& k2 E1 M4 e, z - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
8 i" z; p ?2 \, H7 } - $collention->deleteMany($condition, $options);1 o6 Z) G: Q& K s: g" @: H
- & U8 B' z% f' g
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([' n w& R# G( ], O; C6 H2 n9 g
- '_id' => $tableName//我在自增表中用其它的表名作主键
4 W5 ]. q6 t1 N7 \7 G - ], [1 }, h7 V2 l: ^" ]
- '$inc' => ['id' => 1]//自增; L/ Q9 X. D! p( {2 a8 b' i: T
- ], [- z t2 j* I8 G, o( M; E1 s, H
- '_id' => 0
" z) w$ S9 ^ t3 O - ], [2 c! o7 N' ?* W3 A/ E
- 'new' => 1//返回修改后的结果,默认是修改前的& Z- c+ J$ \4 J1 U1 d4 D
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([3 i; R# c% t9 g9 b6 j& n
- '_id' => $tableName% r+ d7 d4 P* h$ b2 V
- ], [6 L9 K8 ~, H" P
- '$inc' => ['id' => 1]
) }; O& J, n v/ k, z+ z0 `" G$ k4 X% q - ], [
/ D) ?* w% C' ]; \/ T5 U3 b) X* B - 'projection' => ['id' => 1],: Q" O' H! }4 C- \2 C
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER% U) Z2 b3 V) R3 D1 b7 [& z& @. J
- ]);
复制代码 & y6 A7 k( H: g6 n- a! e4 y
+ h$ P3 T; _% N7 d
|