首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Sphinx查询中删除sphinx_deleted?

如何从Sphinx查询中删除sphinx_deleted?
EN

Stack Overflow用户
提问于 2016-03-04 04:34:03
回答 1查看 309关注 0票数 0

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

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

下面是索引文件的定义:

代码语言:javascript
复制
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。

我们使用的是sphinx sphinx-3.1.0和ruby-2.1.0

EN

回答 1

Stack Overflow用户

发布于 2016-03-04 11:58:07

sphinx_deleted属性是由Sphinx创建的,用于以下情况(使用示例中具有核心和增量索引的用户模型的场景):

  • 删除用户时,核心和增量索引中该记录的sphinx_deleted设置为1-如果底层ActiveRecord对象不再存在,则返回Sphinx记录没有意义。
  • 更新用户时,增量索引将使用最新的字段和属性详细信息进行处理,并且核心索引的文档的sphinx_deleted设置为1,因此只有最新(准确)的信息才会匹配。例如,如果用户的名字从Fred更改为Georgina,则搜索'Fred‘将不会返回Georgina,因为会过滤掉核心索引文档(确实匹配)。

这就是该属性存在的原因。你不能告诉Thinking不要添加它,也不能删除那个过滤器,除非在Thinking的内部胡乱摆弄。

如果有想要删除属性和过滤器的特定原因,请随时在此处发表评论,或者您可以在the GitHub repo上打开问题,或发布到TS Google Group

更新

好的,接下来,有三种方法可以绕过它。

选项一:

第一种方法是自己向Sphinx发出查询,使用Thinking连接:

代码语言:javascript
复制
results = ThinkingSphinx::Connection.take do |connection|
  connection.execute "SELECT * FROM user_core, user_delta"
end

请记住,这将返回原始的Sphinx值,而不是ActiveRecord实例。

选项二:

不过,一种更复杂的替代方案是拥有自己的搜索中间件堆栈。首先,您需要创建一个删除:sphinx_deleted过滤器的ThinkingSphinx::Middlewares::SphinxQL的自定义子类:

代码语言:javascript
复制
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查询中间件的新中间件堆栈:

代码语言:javascript
复制
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

然后,您可以在特定的搜索查询中使用该中间件堆栈:

代码语言:javascript
复制
User.search 'foo', :middleware => WithoutFilterMiddleware

值得注意的是,该堆栈中存在两个用于陈旧ids的中间件。它们协同工作以捕获没有匹配ActiveRecord对象的任何Sphinx结果,并重新运行Sphinx查询最多三次,以过滤掉那些不匹配的记录。它们可能很有用,但如果您不想使用它们,可以从自定义堆栈中删除它们。但是,如果没有它们,任何没有匹配ActiveRecord对象的Sphinx记录都将被转换为nils。

选项三:

这是前一个解决方案的更多黑客版本,但将适用于所有搜索,因此可能不值得:使用class_eval重新打开添加过滤器的类,并更改方法定义:

代码语言:javascript
复制
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方法,而是使用一个自定义方法将用户标记为非活动。这避免了回调,从而避免了对上述任何“解决方案”的需要。

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

https://stackoverflow.com/questions/35782462

复制
相关文章

相似问题

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