如果应用了多个过滤器的Sequel Dataset,如何创建一个删除或覆盖其中一个现有过滤器的新数据集?
ds1 = DB[:x].filter(a:1, b:2)
#=> <Sequel::Dataset: "SELECT * FROM x WHERE ((a = 1) AND (b = 2))">
ds2 = ds1.filter(a:42) # I want to CHANGE a, not add another
#=> <Sequel::Dataset: "SELECT * FROM x WHERE ((a = 1) AND (b = 2) AND (a = 42))">
Sequel::Dataset#unfiltered
方法会删除所有过滤器(例如,它会删除b=2
)。虽然在上述简单的情况下很容易重新添加,但在我的实际情况下会导致代码重复。
答案 0 :(得分:1)
您可以将选择规则存储在哈希中并重用哈希:
require 'sequel'
DB = Sequel.sqlite
selection = { a: 1, b: 2 }
ds1 = DB[:x].where( selection )
selection[:a] = 5 #change data
ds2a = ds1.unfiltered.filter(selection) # change selection
ds2b = DB[:x].where( selection ) #Alternative usage
puts ds1.sql #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2))
puts ds2a.sql #SELECT * FROM `x` WHERE ((`a` = 5) AND (`b` = 2))
puts ds2b.sql #SELECT * FROM `x` WHERE ((`a` = 5) AND (`b` = 2))
我发现可以使用新方法filter_exchange
和filter_exchange!
修改数据集。
require 'sequel'
DB = Sequel.sqlite
module Sequel
class Dataset
def filter_exchange!( filter )
filter.each{|key, value|
opts[:where].args.each{|arg|
if arg.args.first == key
arg.args.pop
arg.args << value
end
}
}
self
end
def filter_exchange( filter )
sel = self.unfiltered
filter.each{|key, value|
opts[:where].args.each{|arg|
if arg.args.first == key
sel = sel.filter(key => value)
else
sel = sel.filter(arg)
end
}
}
sel
end
end
end
ds1 = DB[:x].filter(a:1, b:2)
puts ds1.sql #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2))
puts ds1.filter_exchange( a: 7).sql #SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2)
puts ds1.sql #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2)
puts ds1.filter_exchange!( a: 7).sql#SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2)
puts ds1.sql #SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2)
filter_exchange!
修改原始数据集命令!即使ds.dup.filter_exchange!
也会更改您的原始选择。
使用filter_exchange
,您将获得修改后的数据集。 (到目前为止测试不太好。)
答案 1 :(得分:1)
我想这不是他们的主要用例,你可能想要进行基准测试,但你可以使用bound variables
# initial args
ds1 = DB[:x].filter(a: :$a, b: :$b).bind(a: 1, b: 2)
ds1.call(:first) # or :select, :update, et al.
# then later
ds2 = ds1.bind(a: 42)
ds2.call(:first) # uses a = 42 and b = 2
# or pass the args directly into call()
ds2.call(:first, a: 42)
请注意,绑定变量仅在与call
和prepare
一起使用时才会被识别,因此您不能仅使用,例如ds2.first