undefine
@undefine
Senior Software Engineer / PHP

Riak.reduceSlice?

Есть вспомогательный класс для работы с логами, которые лежат в 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
        );
    }
  • Вопрос задан
  • 2884 просмотра
Решения вопроса 1
@Yankovsky
built-in функции:
github.com/basho/riak_kv/blob/master/priv/mapred_builtins.js
github.com/basho/riak_kv/blob/master/src/riak_kv_mapreduce.erl

Из Basho Map-Reduce doc:
Finally, if you want your reduce function to be evaluated only once, after all inputs are received, use this argument instead:

{«reduce»:
{...language, etc. as usual…
«arg»:{«reduce_phase_only_1»:true}}}
Similarly, in Erlang:

{reduce, FunSpec, [reduce_phase_only_1], Keep}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы