【问题标题】:How do I remove sphinx_deleted from a Sphinx query?如何从 Sphinx 查询中删除 sphinx_deleted?
【发布时间】:2016-03-03 20:34:02
【问题描述】:

我是 Ruby 和 ThinkingSphinx 的新手。 我有以下 Sphinx 查询 - SELECT * FROM user_core, user_delta WHERE sphinx_deleted = 0。

我不想看到条件“WHERE 'sphinx_deleted' = 0。如何删除它?我已经从我的 sphinx.conf 文件中删除了 sql_attr_uint = sphinx_deleted,但我看到查询中传递了 sphinx_deleted。

这里是索引文件定义:

ThinkingSphinx::Index.define :user, :with => :active_record, :delta => true do
  indexes [first_name,last_name,display_name], :as=>:name, :sortable=>true
  indexes first_name,     :sortable => true
  indexes last_name,      :sortable => true
  indexes display_name,   :sortable => true
  indexes email,          :sortable => true
  indexes phone,          :sortable => true
  indexes title,          :sortable => true

  has id,          :as => :user_id
  has roles(:id),         :as => :role_ids
  has jurisdictions(:id), :as => :jurisdiction_ids

  set_property :delta =>  true
end

我没有定义 sphinx_scope 或 default_sphinx_scope。

我们正在使用thinking-sphinx-3.1.0 和ruby-2.1.0

【问题讨论】:

    标签: ruby postgresql thinking-sphinx


    【解决方案1】:

    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 方法,而是使用自定义方法将用户标记为非活动状态。这避免了回调,从而避免了对上述任何“解决方案”的需要。

    【讨论】:

    • 帕特,感谢您的快速回复。我需要能够检索某个条件的已删除记录并检索另一个条件的所有记录(标记为已删除和未删除)。如何修改查询,以便有时传入 sphinx_deleted = 1 而在其他时候忽略 sphinx_deleted 条件?
    • 添加了更多细节,但要明确一点:如果你需要这样做,感觉你的实现中的某些东西是不明智的,我建议找到一种不同的方法来处理该功能,而不是使用我建议的任何解决方案。
    • 感谢详细的解决方案。我没有使用destroy来删除记录。如果我们删除用户,则会在用户表中设置一个 deleted_at 列。我不确定为什么 sphinx 没有检索已设置 delete_at 的记录。
    • 我不知道为什么会这样。如果您想使用索引定义以及您正在使用的 Thinking Sphinx 和 Sphinx 的版本来更新问题,这可能会提供一些线索。另外:您的模型上是否有任何 Sphinx 范围(特别是默认范围)?
    • 我已经用索引定义更新了问题。
    猜你喜欢
    • 2012-01-23
    • 2020-07-10
    • 2021-11-09
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    相关资源
    最近更新 更多