|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
7 f/ O& w0 H/ y3 C - ' R- ]) ~5 g$ n( |
- use MongoDB\Driver\Manager;! E t, E7 I0 N3 f
- use MongoDB\Driver\BulkWrite;
! B, U! c3 z* V* Y0 {5 g* g - use MongoDB\Driver\WriteConcern;
2 h+ x" T6 s4 j. W - use MongoDB\Driver\Query;
- H& F! Z5 w4 o- |$ a" { - use MongoDB\Driver\Command;
$ ]. B) H- Z: a2 ]% F
* s/ w2 T" R: D% h0 i- class MongoDb {. I% {; m9 d0 [, s% I/ x" d
- ! S/ a- x4 I7 ?3 N! Q- g: ]4 ^( c
- protected $mongodb;) _9 ^5 |+ r0 V% R! J. m+ u
- protected $database;8 U5 q2 g. m8 H4 O/ b) Y4 n
- protected $collection;
. A+ U. Y/ C* B9 { - protected $bulk;
5 C4 X* r+ h/ F4 s9 S H, j7 l$ s - protected $writeConcern;
( L" S1 J$ |: K - protected $defaultConfig. K: S: d) B# ?. [
- = [
* s6 b' I8 A0 }( H - 'hostname' => 'localhost',3 S% ?: P8 f# \& C& [/ R
- 'port' => '27017',5 x P* H; K( n3 b4 ^9 _
- 'username' => '',7 O, ]$ r% d4 a; ?
- 'password' => '',
* w$ F$ v+ J7 f5 `* v* F: X - 'database' => 'test'
5 v. O3 B: o. d ~0 t - ];+ e( @+ i i4 r% U+ j( d
& n- [0 D; Z8 n- public function __construct($config) {
( k. V2 l% K$ G* r; u - $config = array_merge($this->defaultConfig, $config);
3 D6 u6 K$ D+ J3 d$ w+ \" z+ w8 m - $mongoServer = "mongodb://";# G7 B$ V& q! Z# u3 q
- if ($config['username']) {& |) b( r" O) _1 r$ y: X' k4 T! H
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';( C- M5 x# }& W# |4 c; J
- }" k; s R+ }% o5 m8 n$ w, B- z
- $mongoServer .= $config['hostname'];3 Z+ d* M, `& P( _9 i6 C* G' G" T: t3 D
- if ($config['port']) {; }% I! [- D6 Z. B' O* d ~
- $mongoServer .= ':' . $config['port'];) o" _* Y; O/ s8 F+ X7 r& F7 z' [. j
- }
$ i+ {$ c1 R7 |3 H. Z - $mongoServer .= '/' . $config['database'];. i7 A' |6 Y$ u0 _
0 L- N' u0 b ]( C8 E$ i' K- $this->mongodb = new Manager($mongoServer);
0 E# d: ]6 C. E: H6 C0 W9 a, q - $this->database = $config['database'];
" I) v1 H' K2 @ - $this->collection = $config['collection'];" M' p7 L2 Q. x9 j+ q) ]; V; g
- $this->bulk = new BulkWrite();; b% N G) @1 p0 n0 }, m7 o
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);
5 {5 v0 n# {( g - }
3 R/ b6 ^. s6 \5 O g - , P1 t( n; t6 q5 ^
- public function query($where = [], $option = []) {
% e4 Q2 s/ H1 g& Y: b6 z" n8 j - $query = new Query($where, $option);9 J) Z* k8 [- e; J; F7 h! c
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);+ _; s! M9 w2 d$ X7 N
' t/ G, e+ C, f" S7 n- return json_encode($result);' N5 F' l, ?# L! R
- } a. r% }! m5 b" T/ O
- 6 f4 Q; [# X! p, A7 ]( E( V
- public function count($where = []) {. k4 m- g1 n3 T& f% f' `9 X! g
- $command = new Command(['count' => $this->collection, 'query' => $where]); B9 e$ ?7 k5 w3 T" Y1 z. {
- $result = $this->mongodb->executeCommand($this->database, $command);
# y0 w" A' ?4 d) _% r& g - $res = $result->toArray();4 J$ a! \ A1 L8 e
- $count = 0;
; w0 J* W5 X. s9 o; _6 e6 {3 t5 V$ v - if ($res) {5 {- q! X4 z J4 H. x
- $count = $res[0]->n;
& C* j6 }; u5 o3 I h0 U7 z - }
$ t. _/ _( B% K - # f" E# R; L$ S1 U7 W
- return $count;
+ P5 i: Q' g# a - }
* c* P5 Y8 |. C9 |: G3 c$ A - + z8 C$ Q, p) R- [: q
- public function update($where = [], $update = [], $upsert = false) {
6 j9 S7 T/ l& Z6 Q, C - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);: Z' M' ^; o0 S3 q4 j9 j0 W. c6 U6 S
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);3 x, l1 e! O' W! W8 l, d
- 4 K* K% v* n* k, n0 B4 \0 s
- return $result->getModifiedCount();
: Z2 z8 J2 E3 b- I* B - }
% h: z G' v: @* p9 B
2 f9 Z& t7 }& d* S5 ?- public function insert($data = []) {
0 m8 N3 R% V4 Z0 @/ D - $this->bulk->insert($data);
; B8 \/ A1 B" | T. M - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);1 ]! A% x( t9 |0 _
- 3 o/ G+ ?' N3 Q
- return $result->getInsertedCount();
! `; o* c: D( b - }
* n+ |' w$ t# Z# A2 V L, @ - ! Q' T6 k8 N2 W
- public function delete($where = [], $limit = 1) {
: D7 F N$ o5 ` - $this->bulk->delete($where, ['limit' => $limit]);; _. e% c' V6 }; W
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);# c1 M& Q0 d9 |- f- c1 x% Y( q8 K
- 6 I% X' L& d0 l! N
- return $result->getDeletedCount();
Q2 {2 ^6 c' y s p& B+ L - }
9 _% \- M3 W: B5 g# q% |. X - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接2.新增- 原9 l. q0 b2 U( N; X0 J' I( O+ ^
- $collention->insert($array, $options);
复制代码- $resultOne = $collention->insertOne($array, $options);//单8 w2 d* `% z1 V3 y5 R
- $lastId = $resultOne->getInsertedId();# B& O" q) Q, f5 m. {# p; ^! Y
- $resultMany = $collention->insertMany($array, $options);//多. w% c9 D/ M0 }0 o4 J
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- $collention->update($condition, [
& Q! G; m& Q! q, W- J& v. O - '$set' => $values
5 ]2 v( F# \, A0 c o9 \5 `- A; q - ,[' y3 }9 V( [) s# x2 R5 D
- 'multiple' => true//多条,单条false. n [' N1 w u1 F5 [6 |8 W
- ]);
复制代码- 新$ K8 {; e, ^5 F2 ~6 J* t/ i5 P
- $collection->updateOne(
& U9 |9 C- S$ e - ['state' => 'ny'],
0 f) W# I: c. L u2 j1 Y! j/ S - ['$set' => ['country' => 'us']], i; u; r7 {3 t# G
- );
. n/ m7 N* T' y. T' B - $updateResult = $collection->updateMany(7 _0 }# `$ ?; N1 I1 T8 N4 H3 v5 q
- ['state' => 'ny'],
, d% Z( `/ D* n4 S# l4 i - ['$set' => ['country' => 'us']]2 ~# m6 e( {& E* V G. G
- );
# v1 x3 o2 |% C" M( p% m - $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原/ L- }6 l: k( f* f. C: F
- $cursor = $collection->find($condition, [
x: |3 ?8 W0 G - 'name' => true//指定字段
9 `0 x$ F1 [( m9 o$ T5 R5 F) a. | - ]);" Z2 M8 W y% ~+ j* ^7 g
- $cursor->skip(5);
9 f, q# }: Y* }# u: K1 q - $cursor->limit(5);! F. ?; M9 Q+ l1 E
- $cursor->sort([
- j3 C3 H) G( {8 N7 i* Y - 'time' => -1& F0 u2 k" {; u5 ^# h
- ]);
复制代码- 新
- ]0 a( g; p/ {( Y3 u# o
- $cursor = $collection->find($condition, [! l. z7 {7 p7 |; _ e' R
- 'skip' => 5,
1 n, _% J( x/ h8 N0 z - 'limit' => 5,
6 k# q2 v& J, Z% C9 @ - 'sort' => [$ f4 l- [9 _- W! N9 P6 p. w4 Q, X
- 'time' => -1* G @6 O8 ^1 a
- ],//排序
. ?) \% A$ A) n0 W; ?% G - 'projection' => [9 A, f6 n. k$ z; i! E( @, L
- 'name' => 1//指定字段+ ?% F+ f! F0 ^- N
- ]
* B3 q7 E* M: s - ]);
复制代码 5.删除- 原
9 v: _: z/ T' k9 ]2 t4 K
- $collention->remove($condition, [
- ]2 B/ D A% D9 O; x! j - 'justOne' => false//删单条7 S3 n% |5 |! t. b
- ]);
( c0 Q! I3 W$ }; T2 I - $collention->remove([]);//删所有
复制代码- $result = $collention->deleteOne($condition, $options);
& Q% N& e4 i q1 f2 @+ N" N* L - $collention->deleteMany($condition, $options);( w1 |$ R! B1 j" ~$ P% ?, R
9 u2 U/ A6 _5 e! h" H% I6 j0 ^- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([( Y$ V, {: o9 H, s2 x m3 D
- '_id' => $tableName//我在自增表中用其它的表名作主键
" Z# G% e: u+ N0 N' N6 B - ], [
' m9 N9 a9 B& o! L - '$inc' => ['id' => 1]//自增
6 J7 {+ }" f8 m- h* _8 Q8 C - ], [
" |2 L; @2 |: o" {9 G4 i - '_id' => 09 b% g' B" z- i" P8 M6 f
- ], [
" K$ P* m+ R; S - 'new' => 1//返回修改后的结果,默认是修改前的
% }9 K5 V; b. m+ D' f' b5 S - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([# a" Q$ q2 h9 m, e3 P
- '_id' => $tableName
" C/ D$ b9 r" v% b- A - ], [, e: O8 D' I0 P( f( M
- '$inc' => ['id' => 1]. S7 b1 Y# H( M- m6 H: L5 n; A
- ], [8 Z4 Q4 y0 k# h
- 'projection' => ['id' => 1],
1 q) u7 @, K- h% ^& } - 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
) i" y4 a+ }4 B- l - ]);
复制代码
4 U+ @+ k9 }: [6 `1 m) X# E5 T, w# S
( H4 `8 `$ Y9 e; s+ t5 x Z |