假设我们有一个具有以下迁移的ChessPiece类。
create_table :chess_pieces do |t|
t.string :type
t.integer :row
t.integer :column
t.integer :game_id, index: true
end如果一个主教想要从(0,0)移动到(7,7),那么我需要检查两个位置之间的每个空格,以寻找其他可能阻塞我的主教的部分。如果有一个当铺(5,5)。
我可以查询数据库中可能有如下阻塞部分的每个位置:
pieces = []
8.times do |i|
pieces << ChessPiece.where(game_id: @game_id, row: i, column: i)
end但我想减少查询。或者,我可以为一个游戏抓取所有的棋子,并在中迭代它们,但这似乎也没有效率。我想要做的是告诉数据库将row和column列组合到表单“row-列”中,并称之为position。这样我就可以运行类似于以下查询的内容:
ChessPiece.where(game_id: @game_id, position: ["1-1", "2-2", "3-3"])如何动态创建这个新列,以便运行类似于上述查询的内容?(假设我不能只编辑数据库模式。)
发布于 2019-11-30 20:17:56
可以使用.select创建所需的任意select语句:
@chess_pieces = ChessPiece.select(
"chess_pieces.*",
"CONCAT(chess_pieces.row, '-', chess_pieces.column) AS position"
)使用别名时,结果中的列将作为模型上的一个属性可用:
@chess_pieces.first.position您还可以在WHERE、ORDER和GROUP子句中使用列别名(PG、MySQL),但不是所有dbs:
ChessPiece.select(
"chess_pieces.*",
"CONCAT(chess_pieces.row, '-', chess_pieces.column) AS position"
).where('position = ?', '1-1')
.group('position')
.order('position ASC')对于那些不支持它的人,你需要把它连接起来,聚集起来,或者不管你在原地做什么。
ChessPiece.order("CONCAT(chess_pieces.row, '-', chess_pieces.column)")发布于 2019-12-01 00:34:40
为什么不把这作为一个永久的专栏呢?
添加类型为整型的位置列。创建一个将位置设置为row * 10 + column的预保存钩子
现在可以查询“职位”列。
ChessPiece.where(game_id: @game_id, position: [11, 22, 33])如果需要,还可以重写position=来设置列和行。允许您在写作中使用它。
发布于 2019-12-02 17:31:49
您可以向ChessPiece模型中添加一个助手,以简化构建正确的查询。像这样的事情应该能起作用:
class ChessPiece < ApplicationRecord
def self.matches_position(*positions)
return none if positions.empty?
constraints = positions.map do |row, column|
arel_table[:row].eq(row).and(arel_table[:column].eq(column))
end
where(constraints.reduce(:or))
end
end
ChessPiece.where(game_id: @game_id).matches_position([1, 1], [2, 2], [3, 3])这将导致SQL (根据所使用的数据库语法可能有所不同):
SELECT "chess_pieces".*
FROM "chess_pieces"
WHERE "chess_pieces"."game_id" = 1
AND ("chess_pieces"."row" = 1 AND "chess_pieces"."column" = 1
OR "chess_pieces"."row" = 2 AND "chess_pieces"."column" = 2
OR "chess_pieces"."row" = 3 AND "chess_pieces"."column" = 3)https://stackoverflow.com/questions/59119289
复制相似问题