相关模型的典型Sphinx设置?

时间:2018-03-27 04:48:26

标签: cakephp cakephp-2.0 sphinx

我正在设置Sphinx来搜索数据库,就像我想象的那样是Stack Overflow的核心 - 一个帖子表和一个标签表。每个标记都有一个post_id来标识与之关联的帖子。该网站围绕CakePHP 2.2.3构建。

我想要的是能够搜索主题。也许主题名称出现在帖子的文本中,或者可能出现在与之关联的标签中(有时用户对标签很懒惰)。

我的天真实现(第一次使用Sphinx,并且第一次使用MySQL弄脏了)一直是使用如下的查询设置Sphinx并搜索相关索引:

SELECT posts.id, 
       posts.text,
       tags_concat.all_tags 
FROM   posts 
       LEFT JOIN(SELECT tags.post_id, 
                        GROUP_CONCAT(tags.name) AS all_tags 
                 FROM   tags 
                 GROUP  BY tags.post_id) AS tags_concat 
              ON tags_concat.post_id = posts.id 
WHERE  posts.id >= $start 
       AND posts.id <= $end 

我已经使用了似乎无处不在的Sphinx行为来做到这一点,结果很棒!但是,数据库足够大,我需要使用增量索引来保持合理的最新搜索结果。

我见过的大多数delta方案可能(例如)跟踪主索引中最高的posts.id,并在delta索引中放置任何高于此的值。但是,如果用户编辑帖子,或添加或编辑标签,则可能需要在一个星期之前反映在任一索引中,因为它不会在“帖子”中产生新行。与Stack Overflow不同,我的大部分标记都会在发布后发生,并且帖子在创建后绝对会被编辑(它们是由社区构建的),因此这是一个重要的问题。

我是否遗漏了delta索引的实现,或delta索引的替代方法,或对可能使搜索更可靠的实现的调整?

非常感谢您的时间。

编辑:再考虑一下,我意识到如果在创建帖子后编辑帖子或标签,仍应更新增量索引,但有一个例外 - 在主索引之前创建的帖子重建,但之后编辑(即使这两个事件之间只有一个小时)将不会显示在增量中。我可以在更改时标记帖子(例如,使用posts.in_delta列),然后以某种方式将delta索引的结果覆盖主索引的结果吗?

2 个答案:

答案 0 :(得分:0)

考虑以下因素,并认为我会留在这里作为评论或作为其他人的潜在答案。将此添加到我的主要来源定义:

sql_query_pre = SET NAMES utf8
sql_query_pre = UPDATE posts SET in_delta = 0
sql_query_pre = UPDATE posts SET in_delta = 1 WHERE posts.created > DATE_SUB(NOW(), INTERVAL 7 DAY)

其中posts.created是创建时设置的DATETIME,并为此添加了posts.in_delta。还为主索引的sql_query添加了“WHERE posts.in_delta = 0”,并为delta索引添加了“WHERE posts.in_delta = 1”(当然,只有第一个sql_query_pre行)。 / p>

我的理由是为帖子提供7天的“冷却”期,在这种情况下,需要进行编辑,重新标记,等等。有了上述内容,我的期望是索引将主要反映变化,即使用户不幸在主索引更新之前立即创建帖子。

思想?

答案 1 :(得分:0)

我首选的解决方案是使用delta ids表,例如 delta config ...

sql_query_pre = SELECT @max_id:=max_id, @updated:=updated FROM counter
sql_query_pre = CREATE TEMPORARY TABLE delta_ids (id INT UNSIGNED NOT NULL PRIMARY) \
    SELECT id FROM posts WHERE updated > @updated AND id <= @max_id
sql_query_pre = INSERT IGNORE INTO delta_ids \
    SELECT DISTINCT post_id FROM tags WHERE updated > @updated AND post_id <= @max_id


sql_query = SELECT ... WHERE post.id IN(SELECT id FROM delta_ids) OR post_id > @max_id

sql_query_killlist = SELECT id FROM delta_ids

...它提供了一个在杀戮列表中使用的很好的ID列表:)

有一个非常标准的计数器表,虽然它需要一个时间戳和最后一个帖子ID。

sql_query_pre = REPLACE INTO counter SELECT MAX(id) AS max_id, MAX(updated) AS updated FROM post

sql_qyery_range = SELECT 1, max_id FROM counter

我发现将计数器放在_pre查询(而不是发布)中是最可靠的,这样主要的内容就会被完全相同的标准过滤掉。

(所有内存类型都可能需要尝试以尽可能高效地进行查询。)