1

ActiveRecord, кажется, игнорируют в прикованного запроса AR мой второй order.Цепочка дополнительного заказа по запросу Rails activerecord?

То, что я пытаюсь сделать, - это получить 5 самых читаемых статей в пределах лучших 25 наивысших баллов (например, оцененных пользователями).

Article имеет как read_count (целое число), так и score (float) столбцы, которые я заказываю.

My (? Наивная) попытка была такой запрос:

Article.order("score DESC").limit(25).order("read_count DESC").limit(5) 

Что это возвращает просто первые 5 высшего набрано статьи, а не 5 самых читаемых статей в первой 25 высокий насечкой.

Могу ли я сделать это в одном запросе? Спасибо за любую помощь!

(я на Rails 3.2 и Postgres 9.2)

Добавление

Спасибо Брэду и Филипп Hallstrom два решения этого. Любой из них был бы приемлемым, хотя я пошел с базовым решением brad, как объяснялось в моем комментарии к его ответу.

Профилирования каждого запроса на моей локальной машине развития (MBA) показал решение подзапросов, чтобы быть на 33% быстрее, чем решение Рубина-цикл. Профилирование запросов на моей рабочей машине (Heroku + кран производственной базы данных) показал подзапросы решения быть 95% быстрее! (это через базу данных из 40 000 статей).

Хотя фактическое время, затраченное довольно незначительна, 95% быстрее и 50% меньше строк кода является довольно хорошим решающая.

Ruby-loop solution: (Philip) 
    dev: 24 msec 
    prod: 16 msec 

Sub-query solution: (brad) 
    dev: 22 msec 
    prod: 0.9 msec 

Спасибо и Филиппу, и брату за их ответы!

ответ

3

Просто положить это там без тестирования это, но как насчет этого с подзапросом?

Article.where(id: Article.order("score DESC").limit(25)).order("read_count DESC").limit(5) 
+0

Хорошо, вы получите Tick. Первоначально, потому что есть определенная элегантность для запроса, который является только базой данных, и он, вероятно, масштабируется намного лучше, чем что-то, что нужно сначала подпрыгнуть в Ruby. Но затем я сделал несколько простых профилей времени, когда запрос был получен, и это решение подзапроса в 20 раз быстрее (в производстве), чем цикл Ruby. Очень интересно. Дополнительную информацию см. В дополнении к моему вопросу. –

1

Я не думаю, что вы можете сделать это в одном запросе. Но 25 результатов не так много, чтобы пройти в Ruby land.

Article.order("score DESC").limit(25). 
    sort{|a,b| b.read_count <=> a.read_count }. 
    slice(0,5) 

Вы можете сделать подзапрос или подобное, но я сомневаюсь, что это будет быстрее.

+0

+1 Спасибо, Филипп! Это прекрасно работает. Хотя он чувствует себя немного неэффективным по сравнению с одним запросом, я согласен, что для 25 он вряд ли будет иметь большое значение. Если я не получу одно-запрос или решение только для базы данных, вы получите Tick. –

0

Я не думаю, что вы можете сделать это в одном запросе

Вы могли бы сделать что-то вроде

result = Article.order("score DESC").limit(25) 
result = result.order("read_count DESC").limit(5) 

похож на этот SO ответ Rails: method chaining in model

+0

Извините, это не сработает - это дает тот же результат, что и проблема в вопросе. Фактический запрос не выполняется до тех пор, пока фактически не будет получен «результат». На данный момент это то же самое, что цепляние их по одной строке. (Я не проверял дважды, но я подозреваю, что он генерирует тот же самый SQL.) –

+0

@dj., Моя ошибка, спасибо за отзыв, также оцените добавление к вопросу – user2262149

+0

Нет проблем, спасибо за отправку ответа в любом случае! Я очень ценю время, которое сообщество помогает в этом. –

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