Download & Extend

Mongo alternative to pager_query()

Project:Mongodb
Version:7.x-1.x-dev
Component:Miscellaneous
Category:feature request
Priority:normal
Assigned:carlos8f
Status:needs work

Issue Summary

This is something that has been floating around in my personal code library for a while: a MongoDB version of pager_query(). Pretty useful :) I've implemented it on the Mongo watchdog page for starters.

AttachmentSizeStatusTest resultOperations
mongodb-pager.patch2.8 KBIgnored: Check issue status.NoneNone

Comments

#1

Status:active» needs review

Note that the watchdog table has no pager in the 6.x branch, and in HEAD there is this mess in mongodb_watchdog_overview():

<?php
 
global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
 
$per_page = 50;
 
$page = isset($_GET['page']) ? $_GET['page'] : '';
 
$pager_page_array = explode(',', $page);
 
$on_page = $pager_page_array[0];

 
$cursor = mongodb_collection(variable_get('mongodb_collectionname', 'watchdog'))
    ->
find(mongodb_watchdog_build_filter_query())
    ->
limit($per_page)
    ->
skip($on_page * $per_page)
    ->
sort(array('timestamp' => -1));
?>

Could be cleaned up nicely with this helper. Will port to D7 as well.

#2

Version:6.x-1.x-dev» 7.x-1.x-dev

Ported to HEAD.

AttachmentSizeStatusTest resultOperations
mongo-pager-D7.patch4.33 KBIgnored: Check issue status.NoneNone

#3

mongodb_watchdog_pager_init() can be removed, too.

#4

Status:needs review» needs work

Whoops, I forgot to implement $sort.

#5

An alternative approach which I'm using involves setting the limit() and skip() on the query separately, then using the query cursor to set the global pager variables, like so:

/**
* set the global pager variables from a mongo query cursor,
* so theme('pager') works
*
* DOES NOT run a query or set a limit - has to be set separately on the cursor/query
*  w/ $cursor->skip($page * $per_page)->limit($per_page)
* then this function checks the limit() w/ count(TRUE)
* (see http://www.php.net/manual/en/mongocursor.count.php)
*
* @param $cursor a mongodb cursor, already queried and limit()'d
* @param $element An optional integer to distinguish between multiple pagers on one page. (as in pager_query())
*
* @return nothing [sets global variables]
*/
function mongodb_set_pager($cursor, $element = 0) {
  global $pager_page_array, $pager_total, $pager_total_items;
  $pager_page_array = explode(',', $page);
  $pager_element = 0;
  $pager_total_items[$pager_element] = $cursor->count(FALSE);   // total w/o limit
  $per_page = $cursor->count(TRUE);   // w/ limit
  $pager_total[$pager_element] = ceil($pager_total_items[$pager_element] / $per_page);
  $pager_page_array[$pager_element] = max(0, min((int) $pager_page_array[$pager_element], ((int) $pager_total[$pager_element]) - 1)); 
}

#6

Coming back to this after a while - my function was missing a critical line for $page. Corrected:

function mongodb_set_pager($cursor, $element = 0) {
  global $pager_page_array, $pager_total, $pager_total_items;
  $page = isset($_GET['page']) ? $_GET['page'] : '';

  $pager_page_array = explode(',', $page);
  $pager_element = 0;
  $pager_total_items[$pager_element] = $cursor->count(FALSE);   // total w/o limit
  $per_page = $cursor->count(TRUE);   // w/ limit
  $pager_total[$pager_element] = ceil($pager_total_items[$pager_element] / $per_page);
  $pager_page_array[$pager_element] = max(0, min((int) $pager_page_array[$pager_element], ((int) $pager_total[$pager_element]) - 1));
}

#7

How to use this in some custom module?
I'm using some about code written below: I see pager and docs list, but the list is always the same, there is no reaction to pager surfing..

<?php
try {
   
$m = new MongoClient('mongodb://localhost/');
   
$docs = $m->xxx->publisher_sites->find(array('uid' => (int)$user->uid))->limit(10)->sort(array('_id' => -1));
   
mongodb_set_pager($docs);
   
$build['items']['#markup'] = '';
    foreach(
$docs as $doc) {
     
$id = end($doc['_id']);
     
$build['items']['#markup'] .= $id . '<br/>';
    }
   
$build['pager'] = array(
     
'#theme' => 'pager',
    );
    return
$build;
  } catch (
MongoCursorException $e ) {
   
drupal_set_message($e->getCode() . ': ' . $e->getMessage(), 'error');
  }
 
$m->close();
?>
nobody click here