Yii 1.1: dgsphinxsearch

Wrapper class for SphinxClient library
45 followers

DGSphinxSearch Extension

DoubleGIS company presents Yii extensions for SphinxClient library.

The 'DGSphinxSearch' is a Yii Framework Plugin that provides a Wrapper for SphinxClient interface. Contains all methods of SphinxClient for full text searching and usefull SQL-like interface.

Sphinx is an open source full text search server, designed from the ground up with performance, relevance (aka search quality), and integration simplicity in mind. It's written in C++ and works on Linux (RedHat, Ubuntu, etc), Windows, MacOS, Solaris, FreeBSD, and a few other systems.

Changelog

1.1 - SPH_MATCH_FULLSCAN support added. - SPH_RANK_TOTAL support added - Some bugs fixed

1.0 - Initial release

Requirements

  • Yii 1.1.*
  • Sphinx Client PECL extension (http://pecl.php.net/package/sphinx)

Installation

  • Unpack all files under your project 'component' folder
  • Include your new exteniosn into your project main.php configuration file:
'components' => array(
        ...
        'search' => array(
            'class' => 'application.components.DGSphinxSearch',
            'server' => '127.0.0.1',
            'port' => 9312,
            'maxQueryTime' => 3000,
            'enableProfiling'=>0,
            'enableResultTrace'=>0,
            'fieldWeights' => array(
                'name' => 10000,
                'keywords' => 100,
            ),
        ),
        ...
      )
  • Enjoy!

Usage

Search by criteria Object:

$searchCriteria = new stdClass();
$pages = new CPagination();
$pages->pageSize = Yii::app()->params['firmPerPage'];
$searchCriteria->select = 'project_id';
$searchCriteria->filters = array('project_id' => $project_id);
$searchCriteria->query = '@name '.$query.'*';
$searchCriteria->paginator = $pages;
$searchCriteria->groupby = $groupby;
$searchCriteria->orders = array('f_name' => 'ASC');
$searchCriteria->from = 'firm';
$resIterator = Yii::App()->search->search($searchCriteria); // interator result
/* OR */
$resArray = Yii::App()->search->searchRaw($searchCriteria); // array result

Search by SQL-like syntax:

$search->select('*')->
    from($indexName)->
    where($expression)->
    filters(array('project_id' => $this->_city->id))->
    groupby($groupby)->
    orderby(array('f_name' => 'ASC'))->
    limit(0, 30);
$resIterator = $search->search(); // interator result
/* OR */
$resArray = $search->searchRaw(); // array result

Search by SphinxClient syntax:

$search = Yii::App()->search;
$search->setSelect('*');
$search->setArrayResult(false);
$search->setMatchMode(SPH_MATCH_EXTENDED);
$search->setFieldWeights($fieldWeights)
$resArray = $search->query( $query, $indexName);

Combined Method:

$search = Yii::App()->search->
    setArrayResult(false)->
    setMatchMode(SPH_MATCH_EXTENDED);
$resIterator = $search->select('field_1, field_2')->search($searchCriteria);

Total 20 comments

#15526 report it
rei at 2013/11/19 01:49am
Data provider for sphinx search

Anyone who needs data provider as search result can use additional component written by Yuri! in this thread. It also supports pagination.

Hope that would be useful. Thanks for providing this extension, anyway!

#14807 report it
yiiqs2 at 2013/09/11 09:46am
solved

wow. i confused using this extension.

i execute sphinx not use this. but i use DAO regular. this is guide to execute yii + sphinx and showing result data to grid.

thanks all.. thanks yii..

#14588 report it
yiiqs2 at 2013/08/26 02:16am
failed to implement as $dataprovider TbGridView .

Hi.. this is my code on view.

i implement to TbGridView. $resArray = Yii::app()->search->setMatchMode(SPH_MATCH_ANY)->searchRaw($searchCriteria);

$this->widget('bootstrap.widgets.TbGridView', array(
        'dataProvider' => $resArray,
        'id' => 'order-grid',
        'type' => 'striped',
        'columns' => array(
            array(
                'header' => Yii::t('order', 'Jumlah'),
                'value' => '$data[\'catalogid\']',
            ),
   ),
    ));

i get error messages :

Fatal error: Call to a member function getData() on a non-object in C:\xampp\htdocs\myproject\vendor\yiisoft\yii\framework\zii\widgets\CBaseListView.php on line 111

how to fill sphinx data result into datagrid as $dataprovider ? thank you.

#14587 report it
yiiqs2 at 2013/08/26 12:02am
How to show sphinx result data to datagrid as $dataprovider

Hi all....

How to show sphinx result data to datagrid as $dataprovider? please send here example guidance.**

Thank a lot.

#10789 report it
v_bogdan at 2012/11/23 04:37pm
solution of don't working pagination

You must call twice: Yii::app()->search. I solved problem this way:

$searchCriteria = new stdClass();                     
            $searchCriteria->select = '*';    
            $searchCriteria->query = '@tags *'.$term.'*';            
            $searchCriteria->from = 'test1';
            $pages = new CPagination();                        
            $pages->pageSize =24;    
            $resArray = Yii::app()->search->setMatchMode(SPH_MATCH_ANY)->searchRaw($searchCriteria);
            $pages->itemCount = $resArray['total'];                    
            $searchCriteria->paginator = $pages;
            $resArray = Yii::app()->search->setMatchMode(SPH_MATCH_ANY)->searchRaw($searchCriteria);
#9681 report it
Fred CHu at 2012/09/03 04:49am
How to cache result?

How to cache result?

I use Search by criteria Object.

#9573 report it
Fred CHu at 2012/08/23 10:48pm
How to sort by geo?

I use

if ($fil == 'geo') {
                    $min = (float) (isset($vol['min']) ? $vol['min'] : 0);
                    $point = explode(' ', str_replace('POINT(', '', trim($vol['point'], ')')));
                    $this->client->setGeoAnchor('latitude', 'longitude', (float) $point[1] * ( pi() / 180 ), (float) $point[0] * ( pi() / 180 ));
                    $this->client->setFilterFloatRange('@geodist', $min, (float) $vol['buffer']);

But I don't know how to sort by geo.

#9471 report it
Yuri! at 2012/08/14 10:00am
Error in DGSphinxSearch

Search by criteria Object: ...

$searchCriteria->orders = array('f_name' => 'ASC'); Error: Argument 1 passed to DGSphinxSearch::orderby() must be an instance of DGSort, array given

How to fix:

  • use SQL-like syntax in the order criteria:
$searchCriteria->orders = 'f_name ASC, product_id DESC';
  • replace function:
public function orderby($orders = null)
    {
        $this->criteria->orders = $orders;
        if ($orders) {
            $this->client->SetSortMode(SPH_SORT_EXTENDED, $orders);
        }
        return $this;
    }
#9392 report it
berza at 2012/08/08 08:47am
limit the results

you do not need to get all id's to count total items found. The results array that returned by sphinxAPI along with [matches] returned a [total], [total_found], [request_time], etc rows. You need the total_found row. You can limit matches to 1 but you will see total found as well.

#9389 report it
Fred CHu at 2012/08/08 04:40am
can you post some code sample?

shark

I also don't know how to do on pagiation.

can you post some code sample?

#9384 report it
shark at 2012/08/08 02:29am
Re: How to use paginator?

I get all result id, because if you use paginator in search component, you doesn't know result count, and page number.

#9381 report it
Fred CHu at 2012/08/07 11:49pm
How to use paginator?

how to use paginator in view?

#9222 report it
shark at 2012/07/30 05:18am
orderby bug

Hi,

this is my orderby function:

/**
 * @brief set matches sorting, SQL-like syntax - 'order_by expression'
 * @param array $orders
 * @return $this chain
 */
public function orderby($orders = null) {
    $this->criteria->orders = $orders;
    if ($orders) {      
        array_walk($orders, function(&$item, $key) {
                    $item = $key . ' ' . $item;
        });     
        $this->client->SetSortMode(SPH_SORT_EXTENDED, implode(',', $orders));
    }
    return $this;
}

filters functions (with floating support), thx berza:

/**
 * @brief set query filters, SQL-like syntax - 'additional where_condition'
 * @param array $filters
 * @return $this chain
 */
public function filters($filters)
{
    $this->criteria->filters = $filters;
    //set filters
    if ($filters && is_array($filters)) {
        foreach ($filters as $fil => $vol) {
            // geo filter
            if ($fil == 'geo') {
                $min = (float) (isset($vol['min']) ? $vol['min'] : 0);
                $point = explode(' ', str_replace('POINT(', '', trim($vol['point'], ')')));
                $this->client->setGeoAnchor('latitude', 'longitude', (float) $point[1] * ( pi() / 180 ), (float) $point[0] * ( pi() / 180 ));
                $this->client->setFilterFloatRange('@geodist', $min, (float) $vol['buffer']);
                // usual filter
            } else if ($fil === 'range'){
                foreach ($vol as $attr=>$range) {
                    if (is_float($range['min']) && is_float($range['max'])) {
                        $this->client->SetFilterFloatRange($attr, $range['min'], $range['max']); 
                    } else {
                        $this->client->SetFilterRange($attr, $range['min'], $range['max']); 
                    }
                }
            } else {
 
                $exclude = false;
                if(is_array($vol) && isset($vol['exclude'])) {
                    $exclude = (bool) $vol['exclude'];
                    unset($vol['exclude']);
                }
 
                $this->client->SetFilter($fil, (is_array($vol)) ? $vol : array($vol), $exclude);
            }
        }
    }
    return $this;
}
#7620 report it
berza at 2012/04/03 11:15am
FilterRange

hi all,

this is my filter function:

public function filters($filters)
    {
        $this->criteria->filters = $filters;
        //set filters
        if ($filters && is_array($filters)) {
            foreach ($filters as $fil => $vol) {
                // geo filter
                if ($fil == 'geo') {
                    $min = (float) (isset($vol['min']) ? $vol['min'] : 0);
                    $point = explode(' ', str_replace('POINT(', '', trim($vol['point'], ')')));
                    $this->client->setGeoAnchor('latitude', 'longitude', (float) $point[1] * ( pi() / 180 ), (float) $point[0] * ( pi() / 180 ));
                    $this->client->setFilterFloatRange('@geodist', $min, (float) $vol['buffer']);
                    // usual filter
                } else if ($fil === 'range'){
                    foreach ($vol as $attr=>$range)
                        $this->client->SetFilterRange($attr, $range['min'], $range['max']); 
                } else {
                    $this->client->SetFilter($fil, (is_array($vol)) ? $vol : array($vol));
                }
            }
        }
        return $this;
    }

It allows to make SetFilterRange() API call. Usage:

$searchCriteria->filters = array('range' => array(
  'date'=>array('min'=>$time_from, 'max'=>$time_to),
  'age'=>array('min'=>$min_age, 'max'=>$max_age),
));
#7137 report it
resurtm at 2012/02/26 11:48pm
Bug report

This code:

$searchCriteria->orders=array('base_type'=>'ASC');

Gives following error:

Argument 1 passed to DGSphinxSearch::orderby() must be an instance of DGSort, array given
#7136 report it
resurtm at 2012/02/26 10:22pm
Another extension

Another better extension: https://github.com/mitallast/yii-sphinx

#7049 report it
Rsol at 2012/02/21 12:02pm
exclude

I some modify function for using "exclude". May be it was usefully.

public function filters($filters)
    {
        $this->criteria->filters = $filters;
        //set filters
        if ($filters && is_array($filters)) {
            foreach ($filters as $fil => $vol) {
                // geo filter
                if ($fil == 'geo') {
                    $min = (float) (isset($vol['min']) ? $vol['min'] : 0);
                    $point = explode(' ', str_replace('POINT(', '', trim($vol['point'], ')')));
                    $this->client->setGeoAnchor('latitude', 'longitude', (float) $point[1] * ( pi() / 180 ), (float) $point[0] * ( pi() / 180 ));
                    $this->client->setFilterFloatRange('@geodist', $min, (float) $vol['buffer']);
                } else if ($vol) {
                    $exclude = false;
                    if(is_array($vol) && isset($vol['exclude']))
                    {
                        $exclude = (bool) $vol['exclude'];
                        unset($vol['exclude']);
                    }
                    $this->client->SetFilter($fil, (is_array($vol)) ? $vol : array($vol), $exclude);
                }
            }
        }
        return $this;
    }
#6685 report it
AStron{Z} at 2012/01/28 09:22am
Nice extension

Thx for comfortable work with sphinx in Yii

Misprint here: Include your new exteniosn into your project main.php configuration file:

#6375 report it
shark at 2012/01/04 09:28am
Old dependency

Sphinx Client PECL extension is relative old ("Added support for new API in sphinx 1.10"), some class methods and predefined constants don't exists (e.g. SPH_RANK_SPH04). If you install it, dgsphinxsearch will use it.

#6103 report it
bonnie at 2011/12/12 11:05pm
Nice extension but have a question

First of all can you clearly explain if the example given go in action controller or somewhere else. Also do I need to index sphinx first before use.

Leave a comment

Please to leave your comment.

Create extension