使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php! K E: u6 Y6 k" ]; v
C4 u0 E1 n1 \4 t- use MongoDB\Driver\Manager;
, Z( @% V% p: s5 p - use MongoDB\Driver\BulkWrite;: f$ C* b3 u4 v% }) x8 t1 b
- use MongoDB\Driver\WriteConcern;" w8 v4 [5 f5 \% i! ~
- use MongoDB\Driver\Query; |2 M6 |9 M- J& I
- use MongoDB\Driver\Command;
j5 i" V: E+ |2 M5 ^ - # h7 s8 m" w A6 X" V9 X
- class MongoDb {
' k$ z- A3 W: o- D. c7 | - 4 _' _/ P2 o% h" R* i
- protected $mongodb;' B( V6 I8 X# L# N: W' q
- protected $database;
- }0 Z4 U: ^+ |9 o7 H1 H - protected $collection;$ H, ~" S& l6 l7 G+ k1 x7 x
- protected $bulk;( [/ \; V1 n6 V) c8 z
- protected $writeConcern;, s4 {+ b4 f0 A0 i8 j
- protected $defaultConfig
! n3 O5 }2 G, S - = [
' e" Q2 X- `* ~5 n) R1 c - 'hostname' => 'localhost',6 c% P' Q( J; _# p U# v
- 'port' => '27017',' |0 Z& i; f& r' B
- 'username' => '',3 T% @; t" o9 P
- 'password' => '',% Y$ X' R2 P! O9 J+ G
- 'database' => 'test'
) y2 b+ o7 K: O( ]' V' x" O - ];9 t9 `5 m; Z6 \- t& r P
% S) R2 Y3 T& {- public function __construct($config) {
8 Q! y! I, g: X% ^: J - $config = array_merge($this->defaultConfig, $config);
6 l* C3 h5 \7 T( C) W - $mongoServer = "mongodb://";
% N; F/ M0 }& q; t5 Z# R - if ($config['username']) {
; ]$ H& q8 A& U! Q. X- I3 R - $mongoServer .= $config['username'] . ':' . $config['password'] . '@';. ?) r2 E5 F& i- v
- }
- v8 @) z9 m# Y, X" S! G1 p4 Z" z - $mongoServer .= $config['hostname'];: g4 \- B+ s% ~* |5 ]. ^& w
- if ($config['port']) {
! H s; X2 {/ f1 k - $mongoServer .= ':' . $config['port'];
O# e' e0 I# j4 z0 y5 s; T - }
5 I4 Y' Z' \9 M% d4 z6 @9 L! t - $mongoServer .= '/' . $config['database'];
: Y# K s! L) P$ A9 t% E$ _9 w - % T% P& X2 ~7 G% \* P) k5 T8 h
- $this->mongodb = new Manager($mongoServer);7 \9 V$ N: N; w. E! Y0 Z+ W
- $this->database = $config['database'];
% l* t1 g# [/ E6 W! n - $this->collection = $config['collection'];
; y) Q& L: Y2 w" d - $this->bulk = new BulkWrite();
( x% T s# ^1 L c% q3 f& ` - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);8 l! A; J2 l$ Q/ j% O
- }9 r$ P2 C, q$ t5 R& [
# S. P! ?# K+ K3 D& f+ u- public function query($where = [], $option = []) {
) p7 D$ g# ^0 J/ A3 u8 z - $query = new Query($where, $option);
" k$ o4 F3 T% p, s7 Y) O) A - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);. ?9 A* m6 [7 O6 ]4 q
2 Y* H Z% b k- O; f7 [- return json_encode($result);3 C0 Z3 V: Y2 N) _+ k
- }
8 K0 a% f% _2 x2 i0 @ - " @/ `8 }5 T2 g- w2 Y1 D/ `6 ]1 l1 c
- public function count($where = []) {
6 ]6 ^% I! C+ b8 d4 _& L - $command = new Command(['count' => $this->collection, 'query' => $where]);4 L5 \3 w; U" P; K
- $result = $this->mongodb->executeCommand($this->database, $command);3 r8 @# j0 k0 m5 A3 A; @
- $res = $result->toArray();& E: j, Y! b5 b, B
- $count = 0;; g1 J1 g9 @; a) S5 m9 a
- if ($res) {
( v! L, B Z0 `* @; b - $count = $res[0]->n;
+ |% P! r) A: ^3 D% o2 ^ - }4 \+ {; H# A/ N' l- k8 i
- ) ?* L8 F; A( F+ t; p' \
- return $count;
* h7 l, |. h8 M. l4 } - }5 w1 x& d0 U N+ M# }: D- R- i
, m# G) B6 _3 A6 ~) |$ x- public function update($where = [], $update = [], $upsert = false) {; l/ Z! g" M/ o( c( w; C
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);8 S/ k+ K( w4 x* i7 j5 \3 [3 v$ z
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);3 \2 u* o4 m0 H c% q( k- y
& z/ q0 M- R0 K- u& `( k- return $result->getModifiedCount();
7 s7 ^" S2 o8 m4 G' o - }# f) \( _$ a4 ~2 t# u. l
- % j- x, b; w n3 n4 M
- public function insert($data = []) {
7 a3 F L! Z C) N* y d) ` - $this->bulk->insert($data);
9 M+ Y/ c, q( t6 q3 [2 v, b6 Z - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 P9 G' E- I# N( v. m* r% ]* J2 i
- # P) d) q' e3 c
- return $result->getInsertedCount();
1 Y2 Q# c! A# l* h+ ]2 K9 N - }
- u0 v, V' o+ s# M. m - - b1 i* Z" w- {+ ]% h6 U% T
- public function delete($where = [], $limit = 1) {) K& o, s& Q u, e
- $this->bulk->delete($where, ['limit' => $limit]);
& r/ y; {4 i+ d# p- O7 i; i. A( I- N - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
) [' n/ o3 ]# D* L$ S$ B
5 g: s" s ^- x) t2 `6 x7 j- return $result->getDeletedCount();
5 |+ V$ l* y( |$ v6 D& ?9 _ - }0 m% u9 ^6 w3 ]+ f. H+ k, E
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新! ~/ g* V6 A* ~0 q' S$ L! l
2.新增- 原) z$ [% Y4 c; }) c; F& _
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单) F" v/ j. J# }, n
- $lastId = $resultOne->getInsertedId();
% f% B% P: D1 h, B0 c. b - $resultMany = $collention->insertMany($array, $options);//多# W* q/ M2 G7 B' S; k
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [5 a4 B% K* G* A# u
- '$set' => $values0 U3 h, m3 B, v, ^
- ,[
5 U) J/ d5 o4 R - 'multiple' => true//多条,单条false" g* y" \7 P( |, s* @/ f
- ]);
复制代码- 新
: |3 M/ c5 B: f, a$ Q8 C3 i
- $collection->updateOne(/ ~8 A: M3 m C8 y
- ['state' => 'ny'],4 g' ]9 W" ?" T2 Q
- ['$set' => ['country' => 'us']]
* Y, \/ H! n3 _ - );
_+ `2 T" L: r3 E1 C+ w1 q - $updateResult = $collection->updateMany(% r [. z4 u& ^7 Q+ y& p
- ['state' => 'ny'],, _$ L! G7 I- I
- ['$set' => ['country' => 'us']]: w( }% ^7 a+ p. o
- );+ R" h+ V" A# a
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原8 Y1 n5 U! z# P( j2 g; {
- $cursor = $collection->find($condition, [0 \ \# H5 e t L1 r) W
- 'name' => true//指定字段
, c% v* c7 B* f" a - ]);
# m* D3 W% J6 j; N1 h* b" ` - $cursor->skip(5);2 M5 j8 W( D& ?4 ?
- $cursor->limit(5);
2 X; v# p/ A( S" H+ }1 q" R - $cursor->sort([
, Y+ \4 |/ n. _9 F- m - 'time' => -1
( @9 h: W4 i; F) q- j - ]);
复制代码- $cursor = $collection->find($condition, [+ ]/ [: i5 `% W7 F- o* r5 H% Q
- 'skip' => 5,3 x4 F4 E- {0 ]& h! K ]" Z: T
- 'limit' => 5,
5 N. e9 k1 N: `; h5 d* L _- L - 'sort' => [5 k! _& V" t" N" V$ R$ ~3 A p
- 'time' => -1
1 Z5 k' ]8 g- C( G) L4 {+ ] R - ],//排序
9 R/ H6 J9 L# S3 M3 ] - 'projection' => [
/ T* h1 @4 D) f4 r3 Z9 P7 s4 O- z - 'name' => 1//指定字段, y3 {2 n/ n, }/ C3 z- i
- ]
5 H7 @% n0 M0 V# S7 N, B - ]);
复制代码 5.删除- 原
8 s! Z+ }: F! n0 q( R+ a3 ?
- $collention->remove($condition, [! B7 R" G: s: D* U& K
- 'justOne' => false//删单条
u% |2 Y4 p- g B5 s3 y - ]);8 G+ M! T8 H8 f& I
- $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
: w4 P- K5 M4 F" b' D - $collention->deleteMany($condition, $options);
7 o! {0 r' I2 w2 ~) S( t2 W' a
) v# }- Q9 n/ b: [1 s: l. n- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
3 h. ^/ g% c. R9 w - '_id' => $tableName//我在自增表中用其它的表名作主键
% T( i* }0 I3 S5 r% u4 @( X - ], [
- [! U- m; ]8 c8 P- x - '$inc' => ['id' => 1]//自增
`( m6 A/ `" Z1 H5 [ - ], [$ R4 j8 @4 r: |/ w7 z; N* q G
- '_id' => 0, U" Y4 `+ u9 O4 Y! f0 t6 w" N
- ], [
) y2 E" d+ x: B) e) K& q9 F - 'new' => 1//返回修改后的结果,默认是修改前的
( K1 J! ~ c# p - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
/ D- o0 X1 `: F - '_id' => $tableName
], T$ x; h! L8 s: q' | - ], [
h2 B; j/ B% p0 w$ _* v - '$inc' => ['id' => 1]! l; V, }5 o8 m# ]; k. d7 R( c0 T
- ], [* B0 R0 A+ I$ q& S0 q' R
- 'projection' => ['id' => 1],. G, t `) w. v, q% r. `0 m
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER. _8 i, [/ @7 k( A8 A/ e
- ]);
复制代码 & q/ S9 ?8 ]0 G+ ]( U! E0 D
7 m; m1 |7 p; l |