|
使用 PHP+MongoDB 的用户很多,因为 MongoDB 对非结构化数据的存储很方便。在 PHP5 及以前,官方提供了两个扩展,Mongo 和 MongoDB,其中 Mongo 是对以 MongoClient 等几个核心类为基础的类群进行操作,封装得很方便,所以基本上都会选择 Mongo 扩展。 但是随着 PHP5 升级到 PHP7,官方不再支持 Mongo 扩展,只支持 MongoDB,而 PHP7 的性能提升巨大,让人无法割舍,所以怎么把 Mongo 替换成 MongoDB 成为了一个亟待解决的问题。MongoDB 引入了命名空间,但是功能封装非常差,如果非要用原生的扩展,几乎意味着写原生的 Mongo 语句。这种想法很违背 ORM 简化 DB IO 操作带来的语法问题而专注逻辑优化的思路。 MongoDB 驱动如果使用原驱动的话,大致语法如下: - <?php
* l+ i6 G9 j0 R7 l% l& ^ - , E {! i6 o/ U+ a) Q0 i2 Q
- use MongoDB\Driver\Manager;
2 _4 i( V& u: I8 y8 g& e- a - use MongoDB\Driver\BulkWrite;
0 M' m3 H' c: R: A/ S! x7 e7 E - use MongoDB\Driver\WriteConcern;
& @( x$ E, R2 d+ T& N - use MongoDB\Driver\Query;4 o6 `' q$ r/ D2 B ]/ @
- use MongoDB\Driver\Command;6 f K. E i3 r
- @# E' R! `4 l, F- class MongoDb {
; n3 x( y& D8 [2 X6 d: w! a! t' W B - 2 m. J. U9 \8 y2 {
- protected $mongodb;
^* k" \! d: e% r - protected $database;; ]& ^) O; a' l/ u0 ]5 v# f
- protected $collection;
- v( c, w* f1 O5 E% ^+ D: S' F - protected $bulk;
( D/ @! V8 y6 i4 `1 V' D - protected $writeConcern;" p) [5 t2 o2 W1 }9 Y+ S/ P% w
- protected $defaultConfig
, n" \7 l8 p) F* K4 W1 ^ - = [
- h6 D1 |4 y2 A- J! m& x/ Y8 X# j& T - 'hostname' => 'localhost',
6 Q2 D1 T* }% g% [& u& [ - 'port' => '27017',8 b+ M* H! h, J: T% z' c
- 'username' => ''," I7 Q2 g: z: j' V9 x
- 'password' => '',
+ W7 k k' N- [ - 'database' => 'test'$ |5 q: c; Z* n1 u% H1 k
- ];
1 [% k/ p; H F5 K, K" } - % Y/ y/ [. y2 A3 a+ D
- public function __construct($config) {$ _9 d) u4 v. J4 ^& `
- $config = array_merge($this->defaultConfig, $config);& M# \+ ?+ i: O+ z& ~0 X2 {/ k
- $mongoServer = "mongodb://";
& s( M7 K) d4 h - if ($config['username']) {9 N; C& G, f f
- $mongoServer .= $config['username'] . ':' . $config['password'] . '@';
# S* N$ K1 S! s# e T/ L, ^" b6 @ - }5 ?6 p" k4 }' y
- $mongoServer .= $config['hostname'];/ U! _/ ?' E4 v9 B9 x, T# g# D
- if ($config['port']) {
5 r4 n! [$ v# S: m! d - $mongoServer .= ':' . $config['port'];0 j9 G, X7 I/ c: ?
- }
* ?8 q& T4 Q# j5 P& r: I - $mongoServer .= '/' . $config['database'];
5 |% S+ t- z6 j4 z1 }' U: |. r
0 o7 w6 L4 w, [' M- $this->mongodb = new Manager($mongoServer);# S* ~2 U# |7 Q. C7 [; |: p& k
- $this->database = $config['database'];
' j7 Y$ U! C4 M1 O1 ? - $this->collection = $config['collection'];# ], x. i+ ~/ G2 g, B) `6 J" f8 D
- $this->bulk = new BulkWrite();$ f, c! l, m8 B' d7 G9 m: Z
- $this->writeConcern = new WriteConcern(WriteConcern::MAJORITY, 100);) a. O- _ N' n$ z
- }
. j* |1 r' B. A6 o- O - " W ~# U5 E6 s/ G" z4 w; e
- public function query($where = [], $option = []) {* P3 m5 V& u; m! \% o: K
- $query = new Query($where, $option);
' n7 ~" b, i7 w3 @ - $result = $this->mongodb->executeQuery("$this->database.$this->collection", $query);
6 _6 f* n8 Y, r0 f' m
n, Q/ P0 [( Z3 K" Z* u/ d- return json_encode($result);
8 C) J1 Y; S5 r8 W - }% v' T; {+ F( z9 b" b& T) K
- + s: W. g( _7 @
- public function count($where = []) {
5 x; @8 d& R/ `) j- X% I9 g - $command = new Command(['count' => $this->collection, 'query' => $where]);
9 d, D9 a" H) I( n$ y - $result = $this->mongodb->executeCommand($this->database, $command);
4 N& A/ `6 B6 k - $res = $result->toArray(); A* t/ q! e# z4 y" F; @
- $count = 0;* m2 t `& u' }# P3 m! z, b
- if ($res) {3 d0 ?7 [# m$ {
- $count = $res[0]->n;
9 X7 b8 `* L) P1 }4 ]+ }4 } - }, t3 r! u, O/ W3 h
- ! y1 R0 @4 P9 {& j
- return $count;
* d0 g2 z, B$ ] - }
5 K# ?4 l6 p& n% R3 H - # X/ A& {4 H8 v' Q. K! X
- public function update($where = [], $update = [], $upsert = false) {: D2 N8 n2 {1 W- m/ \
- $this->bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);$ d- I8 R$ ~1 }$ S8 U
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
- ]& n! _# \5 D/ Z T( x5 I: { - , A& g9 t1 V5 W, R# X2 x
- return $result->getModifiedCount();
. g9 P$ ~9 T$ |# z* | - }
. n+ M: U5 q& S; z% c% a
4 ]" L- _) H' l3 k; D- public function insert($data = []) {
1 j# {$ t2 m. f+ S/ Q( I - $this->bulk->insert($data);
6 A% |5 ?/ U6 Q T% R+ P. E - $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
5 z" i2 \1 [9 q! M. e4 E1 M
4 m' p( j @0 \8 ]& P" t! Q0 i3 a" i- return $result->getInsertedCount();
5 b/ ^; s. P5 i! c4 v- c, B. | - }/ U$ `9 p/ T& y/ Y& C8 e# o
/ j) e( l( n( i S- public function delete($where = [], $limit = 1) {5 @. j- x4 s S% c
- $this->bulk->delete($where, ['limit' => $limit]);2 d+ H) Q. h- C% F; c
- $result = $this->mongodb->executeBulkWrite("$this->database.$this->collection", $this->bulk, $this->writeConcern);
- }- G8 u* _2 L. b - ! ?5 ]$ C: ?! p& C
- return $result->getDeletedCount();$ b! \7 X! d- W! m: X) U3 w9 n6 N
- }
% w+ m) |# y. s - }
复制代码这样的语法和之前差异太大,改动不方便,换 PHP MongoDB 库 MongoDB 库1.连接- 原0 H8 \. ?: \. R! @* h, [
- 新
& }% E3 b0 Q6 Y! K- C {, D 2.新增- $collention->insert($array, $options);
复制代码- 新
- S; F5 o( ]7 l+ N7 Y& R
- $resultOne = $collention->insertOne($array, $options);//单- H8 j0 O" ` N- ~5 I5 P
- $lastId = $resultOne->getInsertedId();' ~* p3 z# S- u% K
- $resultMany = $collention->insertMany($array, $options);//多- m& O% E8 K1 H2 X& [
- $count = $resultMany->getInsertedCount();
复制代码 3.修改- 原
/ n; }) h$ [5 O% O6 x! x5 ~; U, A
- $collention->update($condition, [
0 [4 P' n6 B6 E; V7 ?# _0 g% U0 @ - '$set' => $values5 Z3 \' b; |' t3 j" p3 Y7 [& ]2 v5 m
- ,[
: w% t' p7 ~1 r+ g/ J - 'multiple' => true//多条,单条false
4 ~7 Y! G; W8 ^; } - ]);
复制代码- $collection->updateOne(
6 O* N& S& \5 e, q2 a- t+ a - ['state' => 'ny'],
7 R% l8 W& }3 Q) v8 j4 F$ J8 ^ - ['$set' => ['country' => 'us']]! d4 j9 W# O ^& u# X* M K: _
- );
+ L! s5 o0 Z7 S- t u1 a - $updateResult = $collection->updateMany(' c7 N9 a% ^9 ?' k
- ['state' => 'ny'],
. h, d% M1 R8 R2 _ - ['$set' => ['country' => 'us']]
% { M: S+ K9 j - );
& |( |( W0 k+ J: \4 d" a - $count = $updateResult->getModifiedCount();
复制代码 4.查询- $cursor = $collection->find($condition, [3 i9 W, e4 V! c
- 'name' => true//指定字段
7 t! b2 ^' G* O& W - ]);
' g+ o( {4 g0 ~. R - $cursor->skip(5);
. m. b* ]8 l) H5 V' L- U! G - $cursor->limit(5);7 `1 H7 q# a% o9 R
- $cursor->sort([
+ u- v3 P! s+ g# ]- `4 c5 s, L! P - 'time' => -1
" `% O# i; {# A" \: m' t - ]);
复制代码- $cursor = $collection->find($condition, [) o2 F6 u6 j# F: _% Z, `
- 'skip' => 5,
8 `! } U6 Q! {$ t* @( p2 @ - 'limit' => 5,% S, p$ B* F* t4 E' A7 ]8 a& _8 k, p
- 'sort' => [: y/ s' N. {8 x9 N2 w8 a5 j; r
- 'time' => -15 K( z2 y3 ?4 o& _6 w' ^
- ],//排序
4 v$ C1 v! J, C9 ~1 K - 'projection' => [
+ I7 _! K' e8 l3 W - 'name' => 1//指定字段* h# ^: O* ]8 y# D, [: T
- ]
# D3 M! _0 q( ]" A" B+ h - ]);
复制代码 5.删除- $collention->remove($condition, [; f# ^5 O" [. u0 g
- 'justOne' => false//删单条8 f C! ?8 S$ C; T! M
- ]);
. G2 O' l8 h4 L) M; _3 E: |5 M* ? - $collention->remove([]);//删所有
复制代码- 新 `% E/ H4 P% S' w/ g' K& P
- $result = $collention->deleteOne($condition, $options);. X# O8 R4 [- j+ x' b7 ~
- $collention->deleteMany($condition, $options);; i1 R% c- J0 `8 M% f9 _
- ( K6 S) U+ v {( w3 i
- $result->getDeletedCount();
复制代码 补充有些人可能习惯以类似 MySQL 的自增 ID 来处理数据,以前可能使用 findAndModify() 方法来查询并修改: - $collention->findAndModify([
' K+ M5 Z# P& h& K. L! k - '_id' => $tableName//我在自增表中用其它的表名作主键+ k: L. m; C# x3 M7 ^5 z9 n
- ], [
$ P) T4 K* p8 v2 d* | - '$inc' => ['id' => 1]//自增! R9 W l6 G/ q) k7 p
- ], [
7 d) h! C3 n4 s- s/ t# w - '_id' => 0
! b; L+ O# D4 Q& d! k+ ~/ G - ], [
, o2 @7 {/ x/ d1 _7 n- r9 r - 'new' => 1//返回修改后的结果,默认是修改前的
" k+ H i6 k! M2 G0 c - ]);
复制代码现在使用 MongoDB 库的话需要修改为: - $collention->findOneAndUpdate([! F; K! N$ P6 J7 _- z9 A
- '_id' => $tableName
/ i7 k% _) c3 K" X2 Z; e* ~8 j - ], [
3 ^+ t* E' `1 _3 A/ s1 s - '$inc' => ['id' => 1]
/ o& b/ u) e7 o' k9 c' L - ], [
$ |( S: ^! V2 N( i8 S. [) | - 'projection' => ['id' => 1],( H5 h# J: T% Z [
- 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
( W5 j$ v. E" O - ]);
复制代码 : O. ]1 _- S$ u2 T: }' L
# M. r7 w- |$ t8 _ |