这是从PHP使用Sphinx的正确方法吗?

时间:2012-06-16 22:26:53

标签: php mysql search full-text-search sphinx

我刚刚开始使用Sphinx。到目前为止,我已成功安装它,在我的MySQL数据库索引上得到一个名为profiles的表,并且能够使用PHP API获得正确的结果。我正在使用CodeIgniter,因此我将默认的PHP API包装为CodeIgniter库。

无论如何这就是我的代码的样子:

$query = $_GET['q'];
$this->load->library('sphinxclient');
$this->sphinxclient->setMatchMode(SPH_MATCH_ANY);
$result = $this->sphinxclient->query($query);

$to_fetch = array();
foreach($result['matches'] as $key => $match) {
  array_push($to_fetch, $key);
}

数组$to_fetch包含匹配表行的ID。现在我可以使用典型的MySQL查询来让所有相关用户在搜索页面上显示如下:

$query = 'SELECT * FROM profiles WHERE id IN('. join(',', $to_fetch) . ')';

我的问题是:

  1. 这是正确的方法吗?或者是否存在默认" Sphinx的做法"这对性能会更好。

  2. 其次,我现在回来的是匹配的表行的id。我还想要匹配的列中的文本部分。例如,如果有人搜索关键字dog,而profiles表上的用户在其about列中有以下文字:

    I like dogs. I also like ice cream.

  3. 我希望Sphinx能够回归:

    I like <strong>dogs</strong>. I also like ice cream.
    

    我该怎么做?我尝试使用buildExcerpts()功能,但无法使其正常工作。

    修改

    这就是我现在摘录的方式:

    // get matched user ids
    $to_fetch = array();
    foreach($result['matches'] as $key => $match) {
      array_push($to_fetch, $key);
    }
    
    // get user details of matched ids
    $members = $this->search_m->get_users_by_id($to_fetch);
    
    // build excerpts
    $excerpts = array();
    foreach($members as $member) {
    
        $fields = array(
            $member['about'],
            $member['likes'],
            $member['dislikes'],
            $member['occupation']
        );
    
        $options = array(
            'before_match'      => '<strong class="match">',
            'after_match'       => '</strong>',
            'chunk_separator'   => ' ... ',
            'limit'             => 60,
            'around'            => 3,
        );
    
        $excerpt_result = $this->sphinxclient->BuildExcerpts($fields, 'profiles', $query, $options);
        $excerpts[$member['user_id']] = $excerpt_result;
    }
    
    $excerpts_to_return = array();
    foreach($excerpts as $key => $excerpt) {
        foreach($excerpt as $v) {
            if(strpos($v, '<strong class="match">') !== false) {
                $excerpts_to_return[$key] = $v;
            }
        }
    }
    

    正如您所看到的,我正在4个不同的mysql列中搜索每个查询:

    about
    likes
    dislikes
    occupation
    

    因此,我不知道4列中的哪一列包含匹配的关键字。它可以是任何一个,甚至不止一个。所以我别无选择,只能通过BuildExcerpts()函数运行所有4列的内容。

    即使这样,我也不知道BuildExcerpts()使用<strong class="match">标签返回了哪一个。因此,我对stpos返回的所有值进行BuildExcerpts()检查,以便最终获得正确的摘录并将其映射到其所属的配置文件的用户。

    在我需要与4个不同列的内容匹配的情况下,您是否看到了比这更好的方法?

1 个答案:

答案 0 :(得分:6)

是的,看起来很好。要记住从Mysql返回的行可能不会出现在sphinx中的顺序。

有关如何使用FIELD()的信息,请参阅sphinx网站上的常见问题解答,但我个人喜欢将sphinx中的行放入关联数组中,然后通过我列出的sphinx循环并从数组中获取行。以牺牲内存为代价完全避免排序阶段!

至于突出显示,是的,坚持使用buildExcer - 这就是实现它的方法。


编辑添加,这个演示 http://nearby.org.uk/sphinx/search-example5-withcomments.phps 演示了从mysql获取行和在应用程序中“排序”。并建立摘录。