我正在运行一些弹性搜索查询,然后将这些结果转换为Active Record。当然,订单不会保留。
我之前有过这项工作,但现在我正在使用Ruby 2.3.1
和Rails 5.1.1
。
我已经尝试了以下所有解决方案,所以我开始认为这是这个环境的一些错误。
def self.find_ordered(ids)
order_clause = "CASE id "
ids.each_with_index do |id, index|
order_clause << sanitize_sql_array(["WHEN ? THEN ? ", id, index])
end
order_clause << sanitize_sql_array(["ELSE ? END", ids.length])
where(id: ids).order(order_clause)
end
此外:
def self.order_by_ids(ids)
order_by = ["case"]
ids.each_with_index.map do |id, index|
order_by << "WHEN id='#{id}' THEN #{index}"
end
order_by << "end"
order(order_by.join(" "))
end
https://github.com/panorama-ed/order_as_specified gem:
Product.order_as_specified(id: [ids])
https://github.com/khiav223577/find_with_order:
Product.find_with_order([ids])
所有这些都应该有效,但所有这些都在运行后默认回数字顺序。我在控制台中运行它们,因此无法运行代码。
编辑:控制台中的请求示例。
Product.where(id: [100,5,10]).order_by_ids([100,5,10]).pluck(:id)
(127.0ms) SELECT "products"."id" FROM "products" WHERE
"products"."id" IN (100, 5, 10) ORDER BY "products"."id" ASC, case
WHEN id='100' THEN 0 WHEN id='5' THEN 1 WHEN id='10' THEN 2 end
=> [5, 10, 100]
答案 0 :(得分:0)
从日志中查看最终的SQL,我们看到了:
ORDER BY "products"."id" ASC, ...
这表明某个地方正在做的事情:
order(:id)
当您的查询中出现神秘信息时,通常的疑问是模型中的default_scope
。我倾向于认为默认范围是邪恶的,当它们包含order
电话时会加倍。
去寻找默认范围并摆脱它。如果你无法摆脱它(因为某些地方取决于它),那么在添加reorder('')
之前,先将reorder(nil)
或order by case ...
投入查询,然后在其周围进行克制填充或使用reorder('case ... end')
一次性替换ORDER BY
内容;像这样的东西:
def self.order_by_ids(ids)
#... as before
reorder(order_by.join(" "))
end
def self.order_by_ids(ids)
#... as before
reorder(nil).order(order_by.join(" "))
end
def self.order_by_ids(ids)
#... as before
reorder('').order(order_by.join(" "))
end
# etc.
您也可以使用unscope(:order)
,但unscope
可以执行您不想要的事情,因此最好使用reorder
,因为它完全符合您的要求,而不是其他任何内容。
答案 1 :(得分:-1)
保留订单的最简单方法是根据不变的字段进行排序。在Rails中,除非您不使用时间戳,否则created_at
将是一个字段。