Как вы ищете разные условия из одной и той же таблицы соединений?

С этими ассоциациями только результаты увеличения возвращают правильные результаты, но когда я пытаюсь найти вторую ассоциацию, она возвращает 0 результатов.

has_one :magnification,
  :class_name => 'ProductAttribute',
  :foreign_key => 'product_id',
  :conditions => {:key => 'Magnification'}
has_one :objective_lens,
  :class_name => 'ProductAttribute',
  :foreign_key => 'product_id',
  :conditions => {:key => 'Objective Lens Diameter'}

define_index do
  has magnification(:value), :type => :float, :as => :magnification
  has objective_lens(:value), :type => :float, :as => :objective_lens_diameter
end

Используемый пример кода

# returns expected results
Product.search(nil, :with => {:magnification => (8.0..9.0)})

# returns 0 results
Product.search(nil, :with => {:objective_lens_diameter => (31.0..61.0)})

Но когда я меняю порядок define_index, происходит обратное. Таким образом, результаты диаметра объектива возвращают правильные результаты, а результаты увеличения возвращают 0.

Использование Rails v2.2, Thinking-Sphinx в качестве плагина v1.2.12 и Sphinx 0.9.8

Изменить: просмотр сгенерированного значения sql_query показывает, что соединение 2-го атрибута использует неправильные ассоциации, поэтому оно не возвращает ожидаемых результатов.

Упрощенные результаты:

SELECT
  `products`.`id` * 2 + 1 AS `id`,
  `products`.`id` AS `sphinx_internal_id`,
  1234567890 AS `class_crc`,
  `product_attributes`.`value` AS `magnification`,
  `objective_lens_products`.`value` AS `objective_lens_diameter`
FROM `products`
  LEFT OUTER JOIN `product_attributes` ON product_attributes.product_id = products.id
    AND `product_attributes`.`key` = 'Magnification'
  LEFT OUTER JOIN `product_attributes` objective_lens_products ON objective_lens_products.product_id = products.id
    AND `product_attributes`.`key` = 'Objective Lens Diameter'
WHERE `products`.`id` >= $start
  AND `products`.`id` <= $end
GROUP BY `products`.`id`
ORDER BY NULL

person Vizjerai    schedule 15.10.2009    source источник
comment
Этот SQL - ваша проблема. Как и положено, атрибуты продукта присоединяются к продуктам дважды. Но он использует неправильное соединение при сопоставлении ключа с диаметром объектива. Опять же, я чувствую, что это связано с тем, как вы определили свои ассоциации.   -  person EmFi    schedule 16.10.2009
comment
Генерируемый SQL исходит от подключаемого модуля Thinking Sphinx, как я уже отмечал выше, когда добавлял его в сообщение о том, что он был источником проблемы. Нет ничего плохого в том, как были построены ассоциации.   -  person Vizjerai    schedule 16.10.2009


Ответы (4)


Можете ли вы поделиться sql_query, сгенерированным для вашей модели продукта, внутри development.sphinx.conf? Действительно, то, что вы делаете, должно работать для обоих атрибутов, так что может быть ошибка в сгенерированной команде SQL.

person pat    schedule 15.10.2009
comment
Я добавил сгенерированный запрос, удалив ненужные части, и похоже, что сгенерированный SQL не был сгенерирован, как ожидалось. - person Vizjerai; 16.10.2009
comment
@ Пэт, я все еще сталкиваюсь с этой проблемой. Вы исправили эту проблему? - person Anikethana; 03.04.2013
comment
@Anikethana Прошло несколько лет с тех пор, как эта тема была активной. Какую версию Thinking Sphinx вы используете? - person pat; 05.04.2013
comment
@ Пэт, я использую версию «2.0.14». Я не могу обновиться до «3.0», пока не будет выпущена стабильная версия mysql2 «0.3.12». - person Anikethana; 05.04.2013

Материал сфинкса в основном правильный. Нули в поиске лишние. Но я, честно говоря, не думаю, что это то, что вызывает вашу проблему.

Я думаю, что ваша проблема связана с вашими модельными отношениями. В частности, ваша взломанная версия Single Table Inheritance (STI) и то, как Sphinx обрабатывает индексы.

Кажется, что вы по существу пытаетесь продублировать индекс, поэтому он игнорирует второй.

Я не совсем уверен, как это исправить, добавление запросов where к блоку define_index не работает, потому что все операторы where применяются ко всем индексам, определенным впоследствии, и не могут быть перезаписаны, а только добавлены. Thinking sphinx также плохо работает с несколькими индексами в модели, поэтому вы не можете исправить это, переопределив блок define_index.

Thinking-Sphinx 1.2 предоставляет Sphinx Scopes, которые вы, возможно, захотите посмотреть в качестве потенциального решения. К сожалению, он плохо документирован, поэтому я не могу сказать, будет ли он работать или нет.

Учитывая отсутствие хитов в отношении поиска в Google Thinking-Sphinx STI и "Single Table Inheritance". Я ожидаю, что переопределение ваших отношений, позволение рельсам обрабатывать STI, чтобы решить ваши проблемы.

Это включает в себя что-то вроде этого:

class ProductAttribute < ActiveRecord::Base
  belongs_to :product
  inheritance_column => :key
  ...
  common methods and validations to objective\_lens\_diameters and and magnifications
  ...
end

class Magnification < ProductAttribute
  ...
  methods and validations unique to magnifications.
  ...
end

class ObjectLensDiameter < ProductAttribute
  ...
  methods and validations unique to object lens diameters
  ...
end

class Product < ActiveRecord::Base
  has_one :magnification
  has_one :objective_lens

  define_index do
    has magnification(:value), :type => :float, :as => :magnification
    has objective_lens(:value), :type => :float, :as => :objective_lens_diameter
  end
end

Вам может потребоваться миграция, чтобы привести существующие ключевые значения в таблице ProductAttributes в соответствие с тем, что STI ожидает от них.

person EmFi    schedule 15.10.2009
comment
Нули в поиске должны были упростить код, а отправка нулей вернет все результаты. Я был бы в порядке с использованием has_many :product_attributes, если бы я мог настроить таргетинг на определенные атрибуты для фильтрации по этим атрибутам. - person Vizjerai; 16.10.2009

Я решил, что нужно работать, пока не будут исправлены ассоциации sql_query. Производительность хуже, чем при использовании левых соединений, но в то же время уменьшается объем внешнего кода, необходимого для его работы.

Таким образом, индекс определения был изменен, чтобы использовать фрагмент SQL для получения определенного столбца напрямую, вместо того, чтобы полагаться на какие-либо соединения.

define_index do
  has "(SELECT `value` " +
    "FROM `product_attributes` " +
    "WHERE `product_id` = `products`.`id` " +
    "  AND `key` = 'Magnification' " +
    "LIMIT 0, 1)", 
    :type => :float,
    :as => :magnification
  has "(SELECT `value` " +
    "FROM `product_attributes` " + 
    "WHERE `product_id` = `products`.`id` " +
    "  AND `key` = 'Objective Lens Diameter' " +
    "LIMIT 0, 1)", 
    :type => :float,
    :as => :objective_lens_diameter
end

Сгенерированный sql_query

SELECT `products`.`id` * 2 + 1 AS `id`,
  `products`.`id` AS `sphinx_internal_id`,
  123456789 AS `class_crc`,
  IFNULL('987654321', 0) AS `subclass_crcs`,
  0 AS `sphinx_deleted`,
  (SELECT `value`
    FROM `product_attributes`
    WHERE `product_id` = `products`.`id`
      AND `key` = 'Magnification'
    LIMIT 0, 1) AS `magnification`,
  (SELECT `value`
    FROM `product_attributes`
    WHERE `product_id` = `products`.`id`
      AND `key` = 'Objective Lens Diameter'
    LIMIT 0, 1) AS `objective_lens_diameter`
FROM `products`
WHERE `products`.`id` >= $start
  AND `products`.`id` <= $end
GROUP BY `products`.`id`
ORDER BY NULL
person Vizjerai    schedule 16.10.2009

Я исправил это, используя метод быстрого сокращения, не уверенный, хорошо это или нет... Я определил третье отношение, которое включает в себя как отношения, которые я определил ранее только для поиска, так и использовал его в методе define_index. Вы можете увидеть мои отношения здесь - http://stackoverflow.com/questions/15791007/thinking-sphinx-search-for-different-conditions-from-the-same-join-table/15804611#15804611

person Anikethana    schedule 04.04.2013