Hello stackoverflow人员,
我们得到了一个正在发展和成长的Rails项目,我们现在在搜索上遇到了第一个性能问题,因为我们不知道如何正确地利用sphinx来满足我们的需求。 我们有像“Java PHP软件开发人员”这样的搜索查询。我们现在的问题是排名应该适用于多种方式。
作为搜索字段,我们有标签列表,说明和标题。 如果其中一个术语在其中一个字段内,则应该获得例如2个点。更多分数,如果它在更多的领域,但不是多个点,如果它在同一领域不止一次。 下一个问题是我有一个包含同义词的大文件,也应该检查。它看起来像这样:
Java > Java
Java-EE > Java
...
因此,如果发现Java-EE,它也应该获得一些积分,但作为同义词会受到惩罚。
最大点数为5,显示的是5颗星。 任何快速的解决方案都会很好,因为目前它只是在普通的红宝石中完成而且速度很慢,因为我们无法在狮身人面像中正确排名。
如果有另一个搜索引擎的解决方案也很好,因为它可以更改。
提前感谢所有的努力。欢迎所有拼写更正和问题清除问题。
答案 0 :(得分:2)
通过改变使用sphinx的方式,可以解决大多数性能问题。首先,您需要解决在sphinx中索引数据的方式。在索引编制期间执行一些处理将使搜索更快并且结果更相关。其次,解决搜索术语,最后但并非最不重要的是,决定使用的排名算法。
我将使用“title”字段作为示例,但可以为所有字段复制逻辑。
<强>索引强>
向sphinx添加两个字段(“title”和“title_synonyms”)。对于数据库中的每条记录,请执行以下操作: -
对单词执行DISTINCT以删除重复项(“Ruby Developer / Java Developer”将成为“Ruby Developer / Java”。这将阻止记录在搜索时获得两个重复分数。这将进入“标题“
从上面获取DISTINCT标题并使用扩展的同义词等效替换所有单词。我建议将同义词放在DB中以使扩展更容易。然后该文本将成为“Ruby Developer / Java-EE”。必须用所有同义词替换每个单词。如果Java有两个同义词,它们都必须在字段中。这进入“title_synonyms”
<强>搜索强>
因为狮身人面像现在有两个字段,我们可以给它们不同的重量; “title”可以得到“10”的权重,“title_synonyms”的权重为“3”。这意味着记录必须匹配4个同义词,然后才能使其与原始标题的排名高于1。您可以使用重量来满足您的需求。
让我们假设用户正在搜索“Java Developer”。对于搜索短语,请执行以下操作: -
以上规则意味着在sphinx中搜索如下: -
@title“Java Developer”| @title_synonyms“Java-EE”
如果您想要将精确匹配排名高于lexemes,搜索查询将如下所示: -
@title(“Java Developer”|“= Java = Developer”)| @title_synonyms(“Java-EE”|“= Java-EE”)
您需要使用SPH_RANK_PROXIMITY_BM25或SPH_RANK_SPH04来使其正常工作。
<强>排序强>
您可以尝试使用任何内置排名算法来查看结果。我建议SPH_RANK_MATCHANY或SPH_RANK_WORDCOUNT作为开始。
对于Proximity和完全匹配排名,请使用SPH_RANK_PROXIMITY_BM25,SPH_RANK_SPH04或SPH_RANK_EXPR,您可以使用自己的算法。
<强>结论强>
您现在应该拥有快速准确的搜索。您的Ruby应用程序必须完成很少的工作,并且大部分工作都是在sphinx(应该在哪里)完成的。
希望这会有所帮助......
答案 1 :(得分:1)
此性能问题是算法问题。
如果您无法以利用后端工具(如sphinx或数据库引擎)的方式表达问题,那么您正在使用ruby进行处理,这很容易出现性能问题。
首先,尽可能多地使用sphinx(或其他任何搜索引擎)和数据库。进入ruby的数据预先消化得越多,你在ruby代码中所做的就越少,而且可能会更快,因为数据库在过去的半个世纪里经过了高度优化。
因此,例如,在关键词上运行sphinx。同时在同义词上运行sphinx。限制顶部结果的所有答案,并合并结果。这样,您的ruby代码将仅限于可能的高结果,而不必考虑整个条目数据库。
一旦进入红宝石,最重要的是避免高阶算法,即确保使用低阶算法。
在处理原始数据时,如果您将最高结果保存在数组中并尝试对数组进行排序或扫描,那么您将获得N平方顺序。也就是说,您的订单将是原始条目数量和您在阵列中保留的元素数量的乘积。
您的问题的最佳算法是由堆类似容器或b树实现的优先级队列。两者都有N-log-N顺序(N的日志N),或者原始数据记录的数量是您将保存在容器中的项目数的日志的时间。
堆是二叉树,树中的每个节点(不仅是叶子,而是每个节点)都有一个额定记录。每个记录下面的节点都有较低的排名。这称为堆条件。
有添加元素的算法,将排名最高的元素排除在外,并替换维持堆条件的排名最低的元素。在维基百科中查找binary heap。
假设您的网站将显示前100名排名结果。在根位于最低排名的位置保持帮助。通过添加正在处理的前100个原始记录来填充堆。
现在记录101及之后,将其等级与根进行比较。如果新记录排名更高,请使用删除算法将堆减少到99个节点(这将删除堆中排名最低的记录)并将新记录添加到堆中。
完成所有记录后,您将获得前100名排名结果。堆删除算法会以相反的顺序将它们拉出来。