【问题标题】:Thinking Sphinx - nested association with boolean fieldThinking Sphinx - 与布尔字段的嵌套关联
【发布时间】:2014-04-22 12:06:47
【问题描述】:

我有Ruby on Rails 4Thinking Sphinx 3 的项目。我有几个模型:

class Investment < ActiveRecord::Base
  has_many :investment_parts 
end

class InvestmentPart < ActiveRecord::Base
  belongs_to :investment
  has_many :check_orders, dependent: :destroy
  has_many :legal_entity_insurance_companies, through: :check_orders, class_name: "LegalEntities::InsuranceCompany"
end

class CheckOrder < ActiveRecord::Base
  belongs_to :legal_entity_insurance_company, class_name: "LegalEntities::InsuranceCompany"
  belongs_to :investment_part
end

我需要通过 CheckOrders 找到 Investmens,其中包含布尔字段 approved

  create_table "check_orders", force: true do |t|
    ...
    t.boolean  "approved", default: false
  end

所以我尝试了:

ThinkingSphinx::Index.define :investment, with: :active_record do
  indexes investment_parts.check_orders.approved, as: :insuranced_investment
end

但搜索一无所获:

2.0.0p353 :008 > CheckOrder.pluck(:approved)
   (0.6ms)  SELECT "check_orders"."approved" FROM "check_orders"
 => [true, true, true] 
2.0.0p353 :009 > Investment.search("", conditions: {insuranced_investment: true})
  Sphinx  Retrying query "SELECT * FROM `investment_core` WHERE MATCH('@insuranced_investment true') AND `sphinx_deleted` = 0 LIMIT 0, 20 OPTION max_matches=50000; SHOW META" after error: Lost connection to MySQL server during query
  Sphinx Query (3.5ms)  SELECT * FROM `investment_core` WHERE MATCH('@insuranced_investment true') AND `sphinx_deleted` = 0 LIMIT 0, 20 OPTION max_matches=50000
  Sphinx  Found 0 results
 => []

所以我决定尝试属性过滤器:

ThinkingSphinx::Index.define :investment, with: :active_record do
  has investment_parts.check_orders.approved, as: :insuranced_investment_attr
end

但它会产生错误:

$ rake ts:rebuild
Stopped searchd daemon (pid: 15516).
Generating configuration to /Projects/my-project/config/development.sphinx.conf
Sphinx 2.1.4-release (rel21-r4421)
...
using config file '/Projects/my-project/config/development.sphinx.conf'...
...
indexing index 'investment_core'...
ERROR: source 'investment_core_0': expected attr type ('uint' or 'timestamp' or 'bigint') in sql_attr_multi, got 'bool insuranced_investment_attr from field'.
ERROR: index 'investment_core': failed to configure some of the sources, will not index.
...
total 15 reads, 0.000 sec, 0.7 kb/call avg, 0.0 msec/call avg
total 50 writes, 0.000 sec, 0.5 kb/call avg, 0.0 msec/call avg
Started searchd successfully (pid: 15556).

我该如何解决这个问题?

【问题讨论】:

    标签: ruby-on-rails ruby sphinx thinking-sphinx


    【解决方案1】:

    Daiku 说得对,属性会更好地满足您的需求,但事实是 Sphinx 无法处理布尔类型的多值属性。

    因此,需要进行一些工作 - 您需要确保包含与 check_orders 的连接,然后您需要一个 SQL sn-p 将布尔值转换为整数(true为 1,假为 0)。我认为以下应该可以解决问题(选择您正在使用的数据库的选项):

    join investment_parts.check_orders
    
    # for PostgreSQL:
    has "array_to_string(array_agg(DISTINCT (CASE check_orders.approved THEN 1 ELSE 0 END)), ',')",
      as: :insuranced_investment_attr, type: :integer, multi: true
    # for MySQL:
    has "GROUP_CONCAT(DISTINCT (CASE check_orders.approved THEN 1 ELSE 0 END) SEPARATOR ',')",
      as: :insuranced_investment_attr, type: :integer, multi: true
    

    【讨论】:

    • 感谢您的回答,帕特!但是,PostgreSQL 的解决方案无法以某种方式工作。我将您的代码粘贴到我的investment_index 文件中,但之后在重建索引时出现此类错误:indexing index 'investment_core'... ERROR: index 'investment_core': sql_range_query: ERROR: syntax error at or near "THEN" LINE 1: ...ng(array_agg(DISTINCT (CASE check_orders.approved THEN 1 ELS... (DSN=pgsql://serj:***@localhost:5432/my-project_development). 不知道如何解决该问题...
    • 看来我发现了问题!应该是CASE WHEN ...。 :)
    • 再次感谢您的解决方案!为 PostgreSQL 编辑后,它完美运行!太棒了!
    【解决方案2】:

    属性过滤器绝对是布尔字段的最佳选择。尝试告诉 sphinx 属性类型:

    has investment_parts.check_orders.approved, as: :insuranced_investment_attr, type: :boolean
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      相关资源
      最近更新 更多