Posted by carlos8f on December 23, 2010 at 2:12am
2 followers
| 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.
| Attachment | Size | Status | Test result | Operations |
|---|---|---|---|---|
| mongodb-pager.patch | 2.8 KB | Ignored: Check issue status. | None | None |
Comments
#1
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
Ported to HEAD.
#3
mongodb_watchdog_pager_init() can be removed, too.
#4
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..
<?phptry {
$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();
?>