高效mongodb的php分页类(不使用skip)
php  /  管理员 发布于 7年前   162
mongodb分页skip+limit分页要先查出所有结果再去跳过,这样如果查询页面越往后效率越低。
如果能够通过查询条件查出每页结果的最后一条记录,在用最后一条记录作为查询条件去查下一页,这样每次都查询页面size条记录,效率不会差。
具体代码如下:包含mongodb.class.php, page.class.php, test.php
mongodb.class.php mongodb 操作类
复制代码 代码如下:
<?php
function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
{
echo $message, $status_code,PHP_EOL;
exit;
}
//MongoDB操作类
class DB
{
private $CI;
private $config_file = 'MongoDB';
private $connection;
private $db;
private $connection_string;
private $collection = '';
private $host;
private $port;
private $user;
private $pass;
private $dbname;
private $key;
private $persist;
private $persist_key;
private $selects = array();
private $wheres = array();
private $sorts = array();
private $page_sorts = array();
private $limit = 999999;
private $offset = 0;
/**
* --------------------------------------------------------------------------------
* CONSTRUCTOR
* --------------------------------------------------------------------------------
*
* Automatically check if the Mongo PECL extension has been installed/enabled.
* Generate the connection string and establish a connection to the MongoDB.
*/
public function __construct($MONGODB_CONFIG)
{
if(!class_exists('Mongo'))
{
show_error("The MongoDB PECL extension has not been installed or enabled", 500);
}
/**
$config['mongo_host'] = '221.234.43.144';
$config['mongo_port'] = 27017;
$config['mongo_db'] = 'test';
$config['mongo_user'] = '';
$config['mongo_pass'] = '';
$config['mongo_persist'] = TRUE;
*
*/
$this->connection_string($MONGODB_CONFIG);
$this->connect();
}
/**
* --------------------------------------------------------------------------------
* Switch_db
* --------------------------------------------------------------------------------
*
* Switch from default database to a different db
*/
public function switch_db($database = '')
{
if(empty($database))
{
show_error("To switch MongoDB databases, a new database name must be specified", 500);
}
$this->dbname = $database;
try
{
$this->db = $this->connection->{$this->dbname};
return(TRUE);
}
catch(Exception $e)
{
show_error("Unable to switch Mongo Databases: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* SELECT FIELDS
* --------------------------------------------------------------------------------
*
* Determine which fields to include OR which to exclude during the query process.
* Currently, including and excluding at the same time is not available, so the
* $includes array will take precedence over the $excludes array. If you want to
* only choose fields to exclude, leave $includes an empty array().
*
* @usage: $this->mongo_db->select(array('foo', 'bar'))->get('foobar');
*/
public function select($includes = array(), $excludes = array())
{
if(!is_array($includes))
{
$includes = array();
}
if(!is_array($excludes))
{
$excludes = array();
}
if(!empty($includes))
{
foreach($includes as $col)
{
$this->selects[$col] = 1;
}
}
else
{
foreach($excludes as $col)
{
$this->selects[$col] = 0;
}
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents based on these search parameters. The $wheres array should
* be an associative array with the field as the key and the value as the search
* criteria.
*
* @usage = $this->mongo_db->where(array('foo' => 'bar'))->get('foobar');
*/
public function where($wheres = array())
{
foreach($wheres as $wh => $val)
{
$this->wheres[$wh] = $val;
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE_IN PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is in a given $in array().
*
* @usage = $this->mongo_db->where_in('foo', array('bar', 'zoo', 'blah'))->get('foobar');
*/
public function where_in($field = "", $in = array())
{
$this->where_init($field);
$this->wheres[$field]['$in'] = $in;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE_NOT_IN PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is not in a given $in array().
*
* @usage = $this->mongo_db->where_not_in('foo', array('bar', 'zoo', 'blah'))->get('foobar');
*/
public function where_not_in($field = "", $in = array())
{
$this->where_init($field);
$this->wheres[$field]['$nin'] = $in;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE GREATER THAN PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is greater than $x
*
* @usage = $this->mongo_db->where_gt('foo', 20);
*/
public function where_gt($field = "", $x)
{
$this->where_init($field);
$this->wheres[$field]['$gt'] = $x;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE GREATER THAN OR EQUAL TO PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is greater than or equal to $x
*
* @usage = $this->mongo_db->where_gte('foo', 20);
*/
public function where_gte($field = "", $x)
{
$this->where_init($field);
$this->wheres[$field]['$gte'] = $x;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE LESS THAN PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is less than $x
*
* @usage = $this->mongo_db->where_lt('foo', 20);
*/
public function where_lt($field = "", $x)
{
$this->where_init($field);
$this->wheres[$field]['$lt'] = $x;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE LESS THAN OR EQUAL TO PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is less than or equal to $x
*
* @usage = $this->mongo_db->where_lte('foo', 20);
*/
public function where_lte($field = "", $x)
{
$this->where_init($field);
$this->wheres[$field]['$lte'] = $x;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE BETWEEN PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is between $x and $y
*
* @usage = $this->mongo_db->where_between('foo', 20, 30);
*/
public function where_between($field = "", $x, $y)
{
$this->where_init($field);
$this->wheres[$field]['$gte'] = $x;
$this->wheres[$field]['$lte'] = $y;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE BETWEEN AND NOT EQUAL TO PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is between but not equal to $x and $y
*
* @usage = $this->mongo_db->where_between_ne('foo', 20, 30);
*/
public function where_between_ne($field = "", $x, $y)
{
$this->where_init($field);
$this->wheres[$field]['$gt'] = $x;
$this->wheres[$field]['$lt'] = $y;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE NOT EQUAL TO PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is not equal to $x
*
* @usage = $this->mongo_db->where_between('foo', 20, 30);
*/
public function where_ne($field = "", $x)
{
$this->where_init($field);
$this->wheres[$field]['$ne'] = $x;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE OR
* --------------------------------------------------------------------------------
*
* Get the documents where the value of a $field is in one or more values
*
* @usage = $this->mongo_db->where_or('foo', array( 'foo', 'bar', 'blegh' );
*/
public function where_or($field = "", $values)
{
$this->where_init($field);
$this->wheres[$field]['$or'] = $values;
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE AND
* --------------------------------------------------------------------------------
*
* Get the documents where the elements match the specified values
*
* @usage = $this->mongo_db->where_and( array ( 'foo' => 1, 'b' => 'someexample' );
*/
public function where_and( $elements_values = array() ) {
foreach ( $elements_values as $element => $val ) {
$this->wheres[$element] = $val;
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* WHERE MOD
* --------------------------------------------------------------------------------
*
* Get the documents where $field % $mod = $result
*
* @usage = $this->mongo_db->where_mod( 'foo', 10, 1 );
*/
public function where_mod( $field, $num, $result ) {
$this->where_init($field);
$this->wheres[$field]['$mod'] = array ( $num, $result );
return($this);
}
/**
* --------------------------------------------------------------------------------
* Where size
* --------------------------------------------------------------------------------
*
* Get the documents where the size of a field is in a given $size int
*
* @usage : $this->mongo_db->where_size('foo', 1)->get('foobar');
*/
public function where_size($field = "", $size = "")
{
$this->_where_init($field);
$this->wheres[$field]['$size'] = $size;
return ($this);
}
/**
* --------------------------------------------------------------------------------
* LIKE PARAMETERS
* --------------------------------------------------------------------------------
*
* Get the documents where the (string) value of a $field is like a value. The defaults
* allow for a case-insensitive search.
*
* @param $flags
* Allows for the typical regular expression flags:
* i = case insensitive
* m = multiline
* x = can contain comments
* l = locale
* s = dotall, "." matches everything, including newlines
* u = match unicode
*
* @param $enable_start_wildcard
* If set to anything other than TRUE, a starting line character "^" will be prepended
* to the search value, representing only searching for a value at the start of
* a new line.
*
* @param $enable_end_wildcard
* If set to anything other than TRUE, an ending line character "$" will be appended
* to the search value, representing only searching for a value at the end of
* a line.
*
* @usage = $this->mongo_db->like('foo', 'bar', 'im', FALSE, TRUE);
*/
public function like($field = "", $value = "", $flags = "i", $enable_start_wildcard = TRUE, $enable_end_wildcard = TRUE)
{
$field = (string) trim($field);
$this->where_init($field);
$value = (string) trim($value);
$value = quotemeta($value);
if($enable_start_wildcard !== TRUE)
{
$value = "^" . $value;
}
if($enable_end_wildcard !== TRUE)
{
$value .= "$";
}
$regex = "/$value/$flags";
$this->wheres[$field] = new MongoRegex($regex);
return($this);
}
/**
* --------------------------------------------------------------------------------
* ORDER BY PARAMETERS
* --------------------------------------------------------------------------------
*
* Sort the documents based on the parameters passed. To set values to descending order,
* you must pass values of either -1, FALSE, 'desc', or 'DESC', else they will be
* set to 1 (ASC).
*
* @usage = $this->mongo_db->where_between('foo', 20, 30);
*/
public function order_by($fields = array())
{
foreach($fields as $col => $val)
{
if($val == -1 || $val === FALSE || strtolower($val) == 'desc')
{
$this->sorts[$col] = -1;
}
else
{
$this->sorts[$col] = 1;
}
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* LIMIT DOCUMENTS
* --------------------------------------------------------------------------------
*
* Limit the result set to $x number of documents
*
* @usage = $this->mongo_db->limit($x);
*/
public function limit($x = 99999) {
if($x !== NULL && is_numeric($x) && $x >= 1)
{
$this->limit = (int) $x;
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* OFFSET DOCUMENTS
* --------------------------------------------------------------------------------
*
* Offset the result set to skip $x number of documents
*
* @usage = $this->mongo_db->offset($x);
*/
public function offset($x = 0)
{
if($x !== NULL && is_numeric($x) && $x >= 1)
{
$this->offset = (int) $x;
}
return($this);
}
/**
* --------------------------------------------------------------------------------
* GET_WHERE
* --------------------------------------------------------------------------------
*
* Get the documents based upon the passed parameters
*
* @usage = $this->mongo_db->get_where('foo', array('bar' => 'something'));
*/
public function get_where($collection = "", $where = array(), $limit = 99999)
{
return($this->where($where)->limit($limit)->get($collection));
}
/**
* --------------------------------------------------------------------------------
* GET
* --------------------------------------------------------------------------------
*
* Get the documents based upon the passed parameters
*
* @usage = $this->mongo_db->get('foo', array('bar' => 'something'));
*/
public function get($collection = "")
{
if(empty($collection))
{
show_error("In order to retreive documents from MongoDB, a collection name must be passed", 500);
}
$results = array();
$documents = $this->db->{$collection}->find($this->wheres, $this->selects)->limit((int) $this->limit)->skip((int) $this->offset)->sort($this->sorts);
$returns = array();
foreach($documents as $doc):
$returns[] = $doc;
endforeach;
$this->clear();
return($returns);
}
/**
* --------------------------------------------------------------------------------
* COUNT
* --------------------------------------------------------------------------------
*
* Count the documents based upon the passed parameters
*
* @usage = $this->mongo_db->get('foo');
*/
public function count($collection = "")
{
if(empty($collection))
{
show_error("In order to retreive a count of documents from MongoDB, a collection name must be passed", 500);
}
$count = $this->db->{$collection}->find($this->wheres)->limit((int) $this->limit)->skip((int) $this->offset)->count();
$this->clear();
return($count);
}
/**
* 自增ID实现
* return insert_id
*/
private function insert_inc($table)
{
$update = array('$inc'=>array('id'=>1));
$query = array('table'=>$table);
$command = array(
'findandmodify'=>'_increase',
'update'=>$update,
'query'=>$query,
'new'=>true,
'upsert'=>true
);
$id = $this->db->command($command);
return $id['value']['id'];
}
/**
* --------------------------------------------------------------------------------
* INSERT
* --------------------------------------------------------------------------------
*
* Insert a new document into the passed collection
*
* @usage = $this->mongo_db->insert('foo', $data = array());
*/
public function insert($collection = "", $data = array()) {
if(empty($collection))
{
show_error("No Mongo collection selected to insert into", 500);
}
if(count($data) == 0 || !is_array($data))
{
show_error("Nothing to insert into Mongo collection or insert is not an array", 500);
}
try
{
$inc = $this->insert_inc($collection);
$data['_id'] = $inc;
$result = $this->db->{$collection}->insert($data, array('fsync' => TRUE));
if($result['ok'] || $result){
return true;
}
else{
return false;
}
}
catch(MongoCursorException $e)
{
show_error("Insert of data into MongoDB failed: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* UPDATE
* --------------------------------------------------------------------------------
*
* Update a document into the passed collection
*
* @usage = $this->mongo_db->update('foo', $data = array());
*/
public function update($collection = "", $data = array(), $flage = false)
{
if(empty($collection))
{
show_error("No Mongo collection selected to update", 500);
}
if(count($data) == 0 || !is_array($data))
{
show_error("Nothing to update in Mongo collection or update is not an array", 500);
}
unset($data['_id']);
if($flage){
$arr = $this->wheres;
unset($arr['_id']);
if(is_array($arr)){
foreach($arr as $key => $w){
unset($data[$key]);
}
}
}
try
{
$res = $this->db->{$collection}->update($this->wheres, array('$set' => $data), array('fsync' => TRUE, 'multiple' => FALSE));
$this->clear();
return $res;
}
catch(MongoCursorException $e)
{
show_error("Update of data into MongoDB failed: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* UPDATE_ALL
* --------------------------------------------------------------------------------
*
* Insert a new document into the passed collection
*
* @usage = $this->mongo_db->update_all('foo', $data = array());
*/
public function update_all($collection = "", $data = array()) {
if(empty($collection))
{
show_error("No Mongo collection selected to update", 500);
}
if(count($data) == 0 || !is_array($data))
{
show_error("Nothing to update in Mongo collection or update is not an array", 500);
}
try
{
$this->db->{$collection}->update($this->wheres, array('$set' => $data), array('fsync' => TRUE, 'multiple' => TRUE));
$this->clear();
return(TRUE);
}
catch(MongoCursorException $e)
{
show_error("Update of data into MongoDB failed: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* DELETE
* --------------------------------------------------------------------------------
*
* delete document from the passed collection based upon certain criteria
*
* @usage = $this->mongo_db->delete('foo', $data = array());
*/
public function delete($collection, $where)
{
if(empty($collection))
{
show_error("No Mongo collection selected to delete from", 500);
}
if(!$where){
show_error("No data input to delete", 500);
}
try
{
$this->wheres = $where;
$this->db->{$collection}->remove($this->wheres);
$this->clear();
return(TRUE);
}
catch(MongoCursorException $e)
{
show_error("Delete of data into MongoDB failed: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* DELETE_ALL
* --------------------------------------------------------------------------------
*
* Delete all documents from the passed collection based upon certain criteria
*
* @usage = $this->mongo_db->delete_all('foo', $data = array());
*/
public function delete_all($collection = "")
{
if(empty($collection))
{
show_error("No Mongo collection selected to delete from", 500);
}
try
{
$this->db->{$collection}->remove($this->wheres, array('fsync' => TRUE, 'justOne' => FALSE));
$this->clear();
return(TRUE);
}
catch(MongoCursorException $e)
{
show_error("Delete of data into MongoDB failed: {$e->getMessage()}", 500);
}
}
/**
* --------------------------------------------------------------------------------
* ADD_INDEX
* --------------------------------------------------------------------------------
*
* Ensure an index of the keys in a collection with optional parameters. To set values to descending order,
* you must pass values of either -1, FALSE, 'desc', or 'DESC', else they will be
* set to 1 (ASC).
*
* @usage = $this->mongo_db->add_index($collection, array('first_name' => 'ASC', 'last_name' => -1), array('unique' => TRUE));
*/
public function add_index($collection = "", $keys = array(), $options = array())
{
if(empty($collection))
{
show_error("No Mongo collection specified to add index to", 500);
}
if(empty($keys) || !is_array($keys))
{
show_error("Index could not be created to MongoDB Collection because no keys were specified", 500);
}
foreach($keys as $col => $val)
{
if($val == -1 || $val === FALSE || strtolower($val) == 'desc')
{
$keys[$col] = -1;
}
else
{
$keys[$col] = 1;
}
}
if($this->db->{$collection}->ensureIndex($keys, $options) == TRUE)
{
$this->clear();
return($this);
}
else
{
show_error("An error occured when trying to add an index to MongoDB Collection", 500);
}
}
/**
* --------------------------------------------------------------------------------
* REMOVE_INDEX
* --------------------------------------------------------------------------------
*
* Remove an index of the keys in a collection. To set values to descending order,
* you must pass values of either -1, FALSE, 'desc', or 'DESC', else they will be
* set to 1 (ASC).
*
* @usage = $this->mongo_db->remove_index($collection, array('first_name' => 'ASC', 'last_name' => -1));
*/
public function remove_index($collection = "", $keys = array())
{
if(empty($collection))
{
show_error("No Mongo collection specified to remove index from", 500);
}
if(empty($keys) || !is_array($keys))
{
show_error("Index could not be removed from MongoDB Collection because no keys were specified", 500);
}
if($this->db->{$collection}->deleteIndex($keys, $options) == TRUE)
{
$this->clear();
return($this);
}
else
{
show_error("An error occured when trying to remove an index from MongoDB Collection", 500);
}
}
/**
* --------------------------------------------------------------------------------
* REMOVE_ALL_INDEXES
* --------------------------------------------------------------------------------
*
* Remove all indexes from a collection.
*
* @usage = $this->mongo_db->remove_all_index($collection);
*/
public function remove_all_indexes($collectio
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号