2016-03-18 10 views
0

В приложении rails 4 в одной модели у меня есть столбец, содержащий несколько идентификаторов в виде строки с значениями, разделенными запятой.Запрос в столбце строки для одного из значений в массиве, таком как несколько OR (с использованием полнотекстового поиска)

"123,4568,12" 

У меня есть «поиск» двигатель, который я использую для извлечения записей с помощью одной или нескольких значений с помощью полнотекстового поиска PostgreSQL я могу сделать что-то вроде этого, что очень полезно:

records = MyModel.where("my_models.col_name @@ ?", ["12","234"]) 

Это возвращает все записи, которые имеют как 12, так и 234 в целевом столбце. Массив поступает из формы с множественным выбором.

Теперь я пытаюсь сделать запрос, который найдет все записи, в которых есть 12 или 234 строки.

я прыгал, чтобы быть в состоянии сделать что-то вроде:

records = MyModel.where("my_models.col_name IN (?)", ["12","234"]) 

Но это не работает.

Должен ли я перебирать все значения в массиве для построения запроса с несколькими OR? Есть ли что-то более подходящее для этого?

EDIT/TL; DR

@BoraMa ответ является хорошим способом для достижения этой цели.

Чтобы найти все записи, содержащие один или несколько идентификаторов, на которые ссылаются в использовании запроса:

records = MyModel.where("my_models.col_name @@ to_tsquery(?)", ["12","234"].join('|')) 

Вам нужно to_tsquery и объединение с одной трубой | сделать OR как запрос (?).

Чтобы найти все записи, содержащие точно все идентификаторы в использовании запроса:

records = MyModel.where("my_models.col_name @@ ?", ["12","234"]) 

И, конечно, заменить [ "12", "234"] с чем-то вроде params[:params_from_my_form]

Postgres documentation for full text search

+0

Можете вы изменить схему так, чтобы вы не хранили CSV в столбце? Возможно, вместо этого используйте столбец массива PostgreSQL. –

+0

Я просто вижу ваш комментарий. На самом деле я не могу изменить схему, но это хорошая идея для будущего. На данный момент я продолжу использовать преимущество полнотекстового поиска. См. Мое обновление для решения. –

ответ

1

Если вы уже начали использовать полнотекстовый поиск в Postgres, я бы попытался использовать его снова. Я думаю, что вы можете использовать полнотекстовые OR запрос, которые могут быть построены следующим образом:

records = MyModel.where("my_models.col_name @@ to_tsquery(?)", ["12","234"].join(" | ")); 

Это использует оператор | для OR ИНГ полнотекстовых запросов в Postgres. Я не тестировал это и, возможно, вам нужно будет сделать to_tsvector('my_models.col_name'), чтобы это сработало.

Для получения дополнительной информации см. documentation.

+0

Привет, BoraMa, ваш подход кажется очень многообещающим, я думаю, что это действительно может сработать. Позвольте мне попробовать вашу идею, и я вернусь к вам! Благодарю. –

+1

Это работает, вы ведете меня по правильному пути. сложно сказать, что оператор 'OR' для полного текста является единственной' '' их документацией, где не полностью ясно для моей цели. To_tsquery необходим, но не tsvector, который, кажется, предназначен для группировки col, в котором вы хотите выполнить поиск. Я обновлю свой вопрос, чтобы предоставить информацию будущим читателям. Я предлагаю вам также обновить свой ответ. Спасибо за вашу идею. –

+0

Отлично, что вы получили его! Я обновил ответ, основываясь на ваших выводах. – BoraMa

0

Пусть ваши идентификаторы:

а = "1,2,3,4"

Вы можете просто использовать:

ModelName.find(a) 

Это даст вам все записи этой модели, чей идентификатор присутствует в.

+0

Привет, каяль, я думаю, что ваш недостающий пункт. Я не пытаюсь найти модель, на которую ссылаются идентификаторы в запросе. Я пытаюсь найти модель, содержащую ссылки на другую (например: идентификаторы категорий). К сожалению, простая находка не может работать в этом случае. Спасибо, что нашли время ответить! –

0

Я просто думаю, что супер простое решение, мы просто отсортировать идентификаторы в сохранении дозвона MyModel, то запрос должен быть проще:

class MyModel < ActiveRecord::Base 
    before_save :sort_ids_in_col_name, if: :col_name_changed? 

    private 

    def sort_ids_in_col_name 
    self.col_name = self.col_name.to_s.split(',').sort.join(',') 
    end 
end 

Тогда запрос будет легко:

ids = ["12","234"] 
records = MyModel.where(col_name: ids.sort.join(',') 
+0

Привет, спасибо за ваш ответ, но 'where (col_name: ids)' будет точным совпадением, и я не смогу найти записи, содержащие, например, только один из идентификаторов из запроса. И чтобы найти записи, в которых есть все идентификаторы, поиск '@@' идеален, потому что он ищет все слова (или id в моем случае), разделенные запятой. Представьте, что я пытаюсь найти простой запрос, чтобы избежать генерации длинного с большим количеством «OR» в нем (один «OR» для каждого идентификатора). –

 Смежные вопросы

  • Нет связанных вопросов^_^