K
K
Konstantin Chukhlomin2013-02-12 15:47:02
NoSQL
Konstantin Chukhlomin, 2013-02-12 15:47:02

Riak.reduceSlice?

There is an auxiliary class for working with logs that are in Riak.
One node.
Problem with the Riak.reduceSlice function: with correct start and end values, the number of records returned is greater than (end-start). And even with different boundaries, you can get the same data.
Has anyone experienced something similar? How to decide?
I would also appreciate if someone shows the Riak.mapValuesJson function.
PS please do not flame about
* which page should be considered first: from 0 or from 1;
* when to sample: during map or 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
        );
    }

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question