sphinx_deleted 属性由 Thinking Sphinx 创建,用于以下情况(在示例中使用具有核心和增量索引的用户模型场景):
-
当删除用户时,sphinx_deleted 在核心索引和增量索引中的该记录都设置为 1 - 如果基础 ActiveRecord 对象不再存在,则返回 Sphinx 记录没有意义。
-
当用户更新时,增量索引会使用最新的字段和属性详细信息进行处理,并且核心索引的文档已将 sphinx_deleted 设置为 1,因此只会匹配最新(准确)的信息。例如如果用户将其姓名从 Fred 更改为 Georgina,则搜索“Fred”将不会返回 Georgina,因为核心索引文档(匹配)被过滤掉了。
李>
这就是属性存在的原因。您不能告诉 Thinking Sphinx 不要添加它,也不能删除该过滤器,除非在 Thinking Sphinx 的内部乱七八糟。
如果有特定原因要删除属性和过滤器,请随时在此处发表评论,或者您可以在the GitHub repo 上打开问题,或发帖到TS Google Group。
更新
好的,除此之外,还有三种解决方法。
选项一:
第一种方法是自己查询 Sphinx,使用 Thinking Sphinx 连接:
results = ThinkingSphinx::Connection.take do |connection|
connection.execute "SELECT * FROM user_core, user_delta"
end
请记住,这会返回原始 Sphinx 值,不是 ActiveRecord 实例。
选项二:
不过,一个更复杂的选择是拥有自己的搜索中间件堆栈。首先,您需要创建一个自定义的 ThinkingSphinx::Middlewares::SphinxQL 子类,以删除 :sphinx_deleted 过滤器:
class SphinxQLWithoutFilter < ThinkingSphinx::Middlewares::SphinxQL
def call(contexts)
contexts.each do |context|
Inner.new(context).call
end
app.call contexts
end
private
class Inner < ThinkingSphinx::Middlewares::SphinxQL::Inner
def inclusive_filters
super.except :sphinx_deleted
end
end
end
然后,创建一个使用这个新的 SphinxQL 查询中间件的新中间件堆栈:
WithoutFilterMiddleware = ::Middleware::Builder.new do
use ThinkingSphinx::Middlewares::StaleIdFilter
use SphinxQLWithoutFilter
use ThinkingSphinx::Middlewares::Geographer
use ThinkingSphinx::Middlewares::Inquirer
use ThinkingSphinx::Middlewares::ActiveRecordTranslator
use ThinkingSphinx::Middlewares::StaleIdChecker
use ThinkingSphinx::Middlewares::Glazier
end
然后您可以在特定的搜索查询中使用该中间件堆栈:
User.search 'foo', :middleware => WithoutFilterMiddleware
值得注意的是,该堆栈中存在两个用于陈旧 id 的中间件。它们一起工作以捕获没有匹配 ActiveRecord 对象的任何 Sphinx 结果,并重新运行 Sphinx 查询最多 3 次以过滤掉那些不匹配的记录。它们可能很有用,但如果您不想使用它们,可以将它们从自定义堆栈中删除。但是,没有它们,任何没有匹配 ActiveRecord 对象的 Sphinx 记录都将被转换为 nil。
选项三:
这是以前解决方案的更骇人听闻的版本,但将适用于 所有 搜索,因此可能不值得:重新打开使用 class_eval 添加过滤器的类并更改方法定义:
ThinkingSphinx::Middlewares::SphinxQL::Inner.class_eval do
def inclusive_filters
# normally:
# (options[:with] || {}).merge({:sphinx_deleted => false})
# but without the sphinx_deleted filter:
options[:with] || {}
end
end
现在,所有这些都说:我认为您实际上并没有删除用户,但是无论如何都会触发删除回调?因此,用户确实存在,但目前正在被 Sphinx 过滤掉?如果是这样,我强烈建议不要使用 ActiveRecord 的 destroy 方法,而是使用自定义方法将用户标记为非活动状态。这避免了回调,从而避免了对上述任何“解决方案”的需要。