Есть вспомогательный класс для работы с логами, которые лежат в Riak.
Одна нода.
Проблема с функцией Riak.reduceSlice: при корректных значениях start и end, приходит количество записей, больше чем (end-start). И даже при разных границах можно получить одни и те же данные.
Кто-нибудь сталкивался с подобным? Как решать?
Еще буду признателен, если кто-нибудь покажет функцию Riak.mapValuesJson.
PS пожалуйста, не флеймить про
* какую страницу считать первой: с 0 или с 1;
* когда нужно делать выборку: во время map или reduce.
/**
* Выборка из хранилища
* @param string $type имя бакета
* @param array $params массив фильтрации: array( array('key' => '<attrName>', '') )
* @param array $sort
* @param array $limit
*
* @return mixed
*/
public function selectData($type, $params = null, $limit = array(1, 20))
{
$conditions = array();
if (!isset($params) || !is_array($params)) {
$params = array();
}
foreach ($params as $k => $v) {
if (isset($v['key'])) {
$k = $v['key'];
}
$jsKey = $this->makeKey($k);
switch ($v['op']) {
case 'eq': $conditions[] = $jsKey . ' == ' . $v['arg']; break;
case 'lt': $conditions[] = $jsKey . ' < ' . $v['arg']; break;
case 'gt': $conditions[] = $jsKey . ' > ' . $v['arg']; break;
case 'le': $conditions[] = $jsKey . ' <= ' . $v['arg']; break;
case 'ge': $conditions[] = $jsKey . ' >= ' . $v['arg']; break;
case 'ne': $conditions[] = $jsKey . ' != ' . $v['arg']; break;
case 'cmp': $conditions[] = $jsKey . ' == "' . $v['arg'] . '"'; break;
case 'preg': $conditions[] = $jsKey . '.match(/' . $v['arg'] . '/i)'; break;
default: continue;
}
}
if (!count($conditions)) {
$conditions[] = 'true';
}
$page = $limit[0]; // страницы приходят начиная с 1
$pageSize = $limit[1];
$start = ($page - 1) * $pageSize;
$end = $page * $pageSize;
// формируем функцию для выборки по параметрам
$reduce
= '
function(values, arg) {
var result = [];
for (var i = 0; i < values.length; i++) {
if (' . implode(' && ', $conditions) . ') {
result.push(values[i]);
}
}
return result;
}';
$mapReduce = $this->riak
->add($type)
->map('Riak.mapValuesJson')
->reduce($reduce)
->reduce('Riak.reduceSlice', array('arg' => array($start, $end), 'keep' => TRUE));
$data = $mapReduce->run();
return array(
'data' => $data,
'start' => $start,
'end' => $end
);
}