首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调优Sphinx搜索产品搜索

调优Sphinx搜索产品搜索
EN

Stack Overflow用户
提问于 2013-11-27 10:49:43
回答 1查看 1.3K关注 0票数 0

我们有一个非常简单的产品目录,它将产品存储在mysql表中,我们需要构建一个高质量的搜索,以寻找应该尽可能快(并且尽可能相关)工作的产品。产品数据库将相当大(大约500.000种产品),这就是为什么使用“喜欢”而不使用索引的搜索速度非常慢的原因。我们已经尝试过使用mysql全文搜索,这种搜索速度很快,但没有产生令人满意的结果,特别是对于使用数字的搜索(例如"LR-41“,这是一种电池类型)。

我们的产品目录包括许多字段,但我们需要搜索的唯一字段是:

代码语言:javascript
复制
product_id = bigint
title = varchar(255)
description = text

经过许多建议之后,我们终于尝试使用Sphinx搜索,并做出了如下配置:

代码语言:javascript
复制
source mysearch {
  type=mysql
  sql_host=...
  sql_user=...
  sql_pass=...
  sql_port=...
  sql_query_pre = SET NAMES utf8
  sql_query = SELECT product_id, title, description FROM products
  sql_query_info = SELECT * FROM products WHERE product_id=$id 
}

index fulltext { 
    source  = mysearch
    path = /var/lib/sphinxsearch/data/mysearch
    docinfo = extern
    mlock = 0
    morphology = stem_en, metaphone
    min_word_len = 1
    blend_chars = +, &, U+23, -
    blend_mode = trim_both
    html_strip = 1 
}

indexer {
    mem_limit = 256M 
}

searchd {
    listen = 9312 
    # everything else set to default
}

对于网站后端,我们使用PHP,并使用以下代码:

代码语言:javascript
复制
<?php
$sphinx = new SphinxClient();
$sphinx->SetServer('localhost', 9312);
$sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
$sphinx->setFieldWeights(array(
    'product_id' => 10,
    'title' => 7,
    'description' => 3
));
$sphinx->setLimits(0, 200, 1000, 5000);
$sphinx->SetRankingMode(SPH_RANK_PROXIMITY_BM25);
$sphinx->AddQuery($_GET['query'], "fulltext");
$results = $sphinx->RunQueries();
print_r($results);
?>

这只是一个测试搜索的演示脚本,但不管我用于查询的是什么,它都会返回一个完全错误的结果--它匹配的产品甚至不包括我正在搜索的单词(或子字符串)。

以下是我想要达到的规则:

  • 如果查询与" product_id“匹配,则产品的排名应该是最高的(一些经常使用product_id的用户了解product_id并希望通过它进行搜索)
  • 如果查询是“MeterXY-123”,那么它应该匹配包含这两个词或任何一个单词的所有产品(当然,包含这两个字符串的产品应该排得更高)。
  • 如果在标题中找到查询,则应该比在描述中找到查询的级别更高。
  • 如果有人搜索"XY-123“,则应该产生与他搜索"XY123”或"XY 123“相同的结果。
  • 它还应该搜索子字符串--例如,如果产品的标题是"Foobar 123",即使用户搜索"foo bar 123“、"bar 123”、"foobar 12“、"foo”等,也应该返回。
  • 结果也应按某种相关性排序返回。例如,如果我有两个产品"foobar 123“和"foobar 456”,并且用户搜索"foobar 4“,那么这两个产品都应该返回(匹配任何单词),但是第二个产品应该比第一个产品(不包含第4个)更高(因为它也包含第4个)。
  • 产品也应根据价值所在的字段进行排序。在这种情况下,product_id字段具有比标题更大的权重,并且具有比描述更高的权重。

所以问题是-如何正确地配置和使用sphinx + php来生成符合上述标准的搜索结果?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-27 16:00:05

这只是一个测试搜索的演示脚本,但是它返回一个完全错误的结果,不管我用来查询什么。

建议从metaphone中删除morphology。它特别支持“模糊”索引--有点像“声音相似”。但它不能很好地结合堵塞(即stem_en) -导致非常混乱的结果。

事实上,如果设置前缀索引(见下文),您也可以删除词干词干--如果尝试并同时使用这两种情况,很难检测边缘情况。

如果查询与" product_id“匹配,则产品的排名应该是最高的(一些经常使用product_id的用户了解product_id并希望通过它进行搜索)

狮身人面像没有在“全文”索引中包含产品id。你需要复制它。

代码语言:javascript
复制
sql_query = SELECT product_id as id, product_id, name,...  

如果查询是“MeterXY-123”,那么它应该匹配包含这两个词或任何一个单词的所有产品(当然,包含这两个字符串的产品应该排得更高)。

这意味着你想做一个“任意”的搜索。狮身人面像默认为“所有”搜索。要么更改为SPH_MATCH_ANY,,要么重写查询,使之成为“任意”(在单词之间插入“AC.26”或使用仲裁)

如果有人搜索"XY-123“,则应该产生与他搜索"XY123”或"XY 123“相同的结果。

这很诡计多端。您可以尝试将-添加到blend_chars。这将是一种工作。但输入"XY 123“将不匹配产品与"XY123”。我认为解决这个问题并不容易。

有各种各样的统计方法试图重写查询,但从本质上讲,它们是不精确的。

它还应该搜索子字符串--例如,如果产品的标题是"Foobar 123",即使用户搜索"foo bar 123“、"bar 123”、"foobar 12“、"foo”等,也应该返回。

需要使用min_prefix_len来启用前缀搜索,并设置enable_star = 0

但是enable_star=0是被隔离的,所以也许可以使用expand_keywords=1来代替它,这将自动为您添加星星。

结果也应按某种相关性排序返回。

一般来说,这种情况会发生。但如果愿意,可以尝试更改排名模式--有许多选项(但需要使用扩展匹配模式)

产品也应根据价值所在的字段进行排序。

setFieldWeights到高潮了!(你已经做到了!)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20240367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档