|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php1 ^4 T* G$ M) c4 z
# @1 |: X" F' H9 W- use MongoDB\Driver\Manager;# r3 l, N$ A3 Y6 R
- use MongoDB\Driver\BulkWrite;
$ b: Z+ a- w' t+ H - use MongoDB\Driver\WriteConcern;# d/ a1 d& I' Q: B$ U* v. @3 ?
- use MongoDB\Driver\Query;% n" \: z) j' [
- use MongoDB\Driver\Command;( B9 H4 c( `5 O: f# R0 ~
- / p0 p# e1 @& T1 t# c* @6 a, r6 l
- class MongoDb {' L' w+ |& ~6 x6 A; K. C
- % v( X. A& i9 t% ~! ` [* }% g
- protected $mongodb;
* G7 r( [% \; q8 t% Z5 {: O - protected $database;; G' i3 _/ e% B f% m& q @) d
- protected $collection;; M, v/ U1 {3 a7 S9 W1 S* e: m1 ?
- protected $bulk;
+ g3 g$ w) G& _8 E- P6 F# k - protected $writeConcern;9 l1 a& c8 `$ }5 i2 I
- protected $defaultConfig7 o' X3 J: v; t1 U }* [
- = [- t. U( d2 i- T) g% @; |6 s
- 'hostname' => 'localhost',6 ~+ w: A! J0 ?0 x2 x% e! s2 j
- 'port' => '27017',
5 k' D+ G6 x" [* m - 'username' => '',
/ C% H( U! ^) y; H: U0 e$ g. D: [ - 'password' => '',0 i. y. [% ^% @! _, y/ I n
- 'database' => 'test'/ A& \8 C( d5 B8 }* U
- ];& Q" W3 Y- I4 T
- ' r D' d a6 x& e4 v8 C
- public function __construct($config) {
- V# `: \' J! Y0 d - $config = array_merge($this->defaultConfig, $config);) I% x5 r. Z- q! X, P
- $mongoServer = "mongodb://";) Y* ]# ^$ G; f, _, u
- if ($config['username']) {. p7 V8 ]! [5 \/ v% r
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';$ Y- v+ `! Y, [
- }
, G$ [+ C; I# F: J# a. y1 j - $mongoServer .= $config['hostname'];5 I( Y5 Y$ R( n1 y" J x
- if ($config['port']) {9 q) }5 H+ l+ b, M+ @* P" V
- $mongoServer .= ':' . $config['port'];
) S5 x8 @& c' [/ n f1 o4 ] - }8 i6 A/ |2 |( p( Y
- $mongoServer .= '/' . $config['database'];
, G6 ~7 ~5 _5 p/ R$ o# t3 C$ {: k8 y - ; [8 S) o2 j4 g9 g3 f
- $this->mongodb = new Manager($mongoServer);
/ q% x: C8 o* X% G& f- ? - $this->database = $config['database'];
2 |4 {+ k. Z# Q2 m+ f1 d. O - $this->collection = $config['collection'];. V; d* t; A s
- $this->bulk = new BulkWrite();
4 j. \3 G- C/ m - $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);" k# _) Z! e0 |5 B+ Q
- }" Y$ g6 z* u2 N) t, L. H& x
- 9 v8 a. m+ F- k' E* ^
- public function query($where = [], $option = []) {- ]" `0 @1 H2 U4 m( p
- $query = new Query($where, $option);8 {) X3 v4 F: Q& H# m: O+ \" P. H X
- $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);% a7 Q4 _5 ?" x7 W9 j
& [2 m8 b! H0 h% Y# `- return json_encode($result);
! p( I" _! f% c2 N' u - }
! i) E( ^$ l; S3 C( I9 X& {, o - ' I$ W! {$ @% x
- public function count($where = []) {! {0 f; x0 t$ H: o+ C0 Y
- $command = new Command(['count' => $this->collection, 'query' => $where]);" w5 f% l" H# S/ Y. P
- $result = $this->mongodb->executeCommand($this->database, $command);6 x- N5 G% Q4 C4 {
- $res = $result->toArray();
8 h; ^; b, g6 r+ `9 w - $count = 0;
% u; U: L, w, C! V, M3 s' T7 z - if ($res) {' d& k# P5 b' l- O/ U" r
- $count = $res[0]->n;
. f: {, R9 c Q4 p# `6 N - }1 G5 k# C3 ]+ B' t3 e; F% n
* L- G: a6 o2 b2 J- return $count;
^$ I' X' U$ R$ P% W - }
& Q5 k( Y+ f7 a% M
5 r; e$ b& f! j+ E g* x+ E- public function update($where = [], $update = [], $upsert = false) {
: z. O" q+ w# v8 Q# v - $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);
2 j* ]8 d! q* [1 p" J - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);% N; Y" s9 ?+ ]7 U
- x7 x O e. K: M4 ~$ D6 w
- return $result->getModifiedCount();
1 r: b0 O5 ^$ Z - }
4 M( K/ A: u8 j4 W& `" m; F) o/ r
6 S8 W/ d( _ P% E' T5 M1 ~- public function insert($data = []) {5 P% F8 S r& e: o( ?$ m5 o
- $this->bulk->insert($data);8 j+ F7 F$ p3 m5 x
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
* c8 |/ a, p V, P, K0 G3 I
3 \( o1 _: M' w! f& K1 S- return $result->getInsertedCount();( D8 z0 M- ~, A) h: J
- }
& }) |" P5 {' b. P - t+ x6 F$ h( ]' u2 @! q! X
- public function delete($where = [], $limit = 1) {
- z: x! H0 Q: C# Q - $this->bulk->delete($where, ['limit' => $limit]);
, C T! l K; l9 ~, |$ f6 \; h - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
" |& P8 }3 [! z& I- T6 L. y - : T: s! ?6 x' k1 m$ w+ c
- return $result->getDeletedCount();
% q1 c! @7 p% P% S" x2 I5 p/ X! C - }( V: ~! g. X6 }. _ Z5 k m; B5 d! X
- }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 新$ D$ V/ N$ A& ?/ @7 w# |6 g
2.新增- $collention->insert($array, $options);
复制代码- 新7 y9 B! P) ?4 E" X Z; r5 f/ n4 z
- $resultOne = $collention->insertOne($array, $options);//单, H6 U y. _" k: V: i, r4 b
- $lastId = $resultOne->getInsertedId();
+ v! f2 e% d# k, M - $resultMany = $collention->insertMany($array, $options);//多
% [) [$ n! I! g8 W5 B - $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
& V3 [. }9 V' M4 H5 c: v! O
- $collention->update($condition, [
. n# v0 ^7 Q+ b; v* p* { - '$set' => $values" x/ `- W* ~& w; l+ W) C' @$ q* c8 ?2 U9 P
- ,[
0 N" _4 k- y! m3 `1 }( F/ ]+ V, [ - 'multiple' => true//多条,单条false
( \; @3 _ R* l0 H% s6 R9 A$ k - ]);
复制代码- 新3 {; w% H% t7 F! x1 m5 {6 f
- $collection->updateOne(
, Y# q& e% b+ K9 j# n7 Q - ['state' => 'ny'],
& u" }1 e1 s. F% f - ['$set' => ['country' => 'us']]# [: m$ M* M: ^: Y
- );
* u2 T+ V& S, V% z [4 I r8 z2 Z" F7 w - $updateResult = $collection->updateMany(
1 n; x' a; l9 f+ {! a" G( P - ['state' => 'ny'],5 E( Q l' q- ?5 w0 Q9 N
- ['$set' => ['country' => 'us']]
8 }8 \! @0 J$ O( l6 u- H S2 G1 r5 q: o - );) `4 z$ L" u* H( v! n" p! [
- $count = $updateResult->getModifiedCount();
复制代码 4.查询- 原
$ M1 Q# h) ?8 b& @: z j; E1 h
- $cursor = $collection->find($condition, [
8 q/ T: E8 ?6 `3 j - 'name' => true//指定字段4 v3 j6 m, y8 M1 F, L+ ]5 @( f
- ]);
' b$ g. ~- @( F/ n/ ]" m - $cursor->skip(5);- R8 L# A) G, `$ ~8 ]
- $cursor->limit(5);8 q) N) w! E1 w4 H
- $cursor->sort([
# B7 F6 v4 m6 ?* j - 'time' => -15 ]- M: j7 V& d
- ]);
复制代码- $cursor = $collection->find($condition, [
0 b, o% M7 Q# [ - 'skip' => 5,; M( y% g( S1 f p# Z* e
- 'limit' => 5,7 G. U! q. O' g- r! n: p
- 'sort' => [# e- h4 C% n% a; l8 ^" N
- 'time' => -1
1 J9 J: q3 H0 b, f! Z - ],//排序
& N; @6 U+ Z+ s! [ - 'projection' => [0 F2 E1 Z4 B* X0 c' r
- 'name' => 1//指定字段( X, C8 p: _8 i* F; {
- ]
5 }# S- c4 [; C d - ]);
复制代码 5.删除- 原
( _# o4 }/ w6 U- f$ C2 x
- $collention->remove($condition, [
: H# h9 C- S, }* @ E$ n4 L( U - 'justOne' => false//删单条
" g( D3 h8 Q1 u6 b" H: Z - ]);3 [: g9 h/ c' ~ p2 `9 p
- $collention->remove([]);//删所有
复制代码- 新0 V9 {" H- Z% l6 J% G# G# U; B
- $result = $collention->deleteOne($condition, $options);
! y! g: Y8 ~: v( C" G - $collention->deleteMany($condition, $options);2 z6 [" ?& `) B) Y" g+ u; c% P
- 5 ]; T$ l4 L: K8 h; z3 `2 h
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([8 ~6 J5 ^ Q1 @& T$ G) j9 }8 o9 B
- '_id' => $tableName//我在自增表中用其它的表名作主键$ l0 A( R6 Z: U5 R4 E( c
- ], [
: S, i0 X& w: C, ? - '$inc' => ['id' => 1]//自增
' u8 V) w6 _+ Y - ], [* N) r9 k1 A( l- H5 x
- '_id' => 0
' ?) U: \& u/ s - ], [
/ t$ P, [+ |2 H1 y. \+ \ - 'new' => 1//返回修改后的结果,默认是修改前的0 S& b# V( a/ r* `+ A* M: a+ P7 |* h% Z2 G
- ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([
. A5 v7 z. K3 G - '_id' => $tableName
, x" V- F; O3 j; O - ], [
2 N }" M! l$ ~/ q7 q% N, j2 F# | - '$inc' => ['id' => 1]
! s1 C t- l. i1 Z& j - ], [
+ A: N7 v8 i: a8 M- ?0 @4 C - 'projection' => ['id' => 1],$ N+ h& U* C' ]" ^
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
# R, \$ [7 L+ T2 ^ - ]);
复制代码 0 S3 G7 x6 a. E, R% I: z" X7 O' ^
0 Z9 p4 w @- ]$ _ |