我正在尝试查询:
我使用较新版本的ruby获得了一些语法,但它不能与我的2.2.1版本一起工作。我的语法是
def self.get(code)
where(code: normalize_code(code)).
where("coupon_count > ? OR coupon_count IS NULL", 0).
where("expires_at > ? OR expires_at IS NULL", Time.now).
take(1)
end
这会引发错误wrong number of arguments (2 for 1)
,这是因为我的导轨似乎无法识别2个参数(" coupon_count>?或coupon_count IS NULL",0)所以我我试图改变它,但是当我把它们变成这样的东西时(在我心里感到可怕的错误)
def self.get(code)
where(code: normalize_code(code)).
where(coupon_count: self.coupon_count > 0 || self.coupon_count.nil? ).
where(expires_at: self.expires_at > Time.now || self.expires_at.nil? ).
take(1)
end
我得到undefined method `coupon_count' for Coupon:Class
我缺乏想法可以帮助我在模型中获取此get方法的语法吗?顺便说一下,如果重要的话,我正在使用mongoid 5.1.0
答案 0 :(得分:1)
您已经定义了一个类方法,因此在这种情况下self
引用Coupon
类而不是Coupon
实例。
尝试以下方法:
scope :not_expired, -> { where("expires_at > ? OR expires_at IS NULL", Time.now) }
scope :previously_used, -> { where("coupon_count > 0 OR coupon_count IS NULL") }
def self.get(code)
previously_used.not_expired.find_by!(code: normalize_code(code))
end
答案 1 :(得分:1)
我感觉到你的痛苦。在MongoDB中组合OR和AND有点乱,因为你根本就没有真正使用查询语言,你只是构建一个哈希。如果您可以将多个条件应用于同一字段,则会出现类似的并发症这就是为什么你不能像ActiveRecord那样包含类似SQL的片段。
例如,表达:
"coupon_count > ? OR coupon_count IS NULL", 0
你需要建立一个像:
这样的哈希:$or => [
{ :coupon_count.gt => 0 },
{ :coupon_count => nil }
]
但是如果你尝试添加另一个OR,你将覆盖现有的:$or
密钥并引起混淆。相反,你需要知道会有多个OR并通过说:$and
手动避免重复:
:$and => [
{
:$or => [
{ :coupon_count.gt => 0 },
{ :coupon_count => nil }
]
}, {
:$or => [
{ :expires_at.gt => Time.now },
{ :expires_at => nil }
]
}
]
然后直接添加code
条件:
:code => normalize_code(code),
:$and => [ ... ]
这使整个事情成为一个相当可怕的怪物:
def self.get(code)
where(
:code => normalize_code(code),
:$and => [
{
:$or => [
{ :coupon_count.gt => 0 },
{ :coupon_count => nil }
]
}, {
:$or => [
{ :expires_at.gt => Time.now },
{ :expires_at => nil }
]
}
]
).first
end
您也可以使用find_by(that_big_mess)
代替where(that_big_mess).first
。此外,如果您希望查询匹配多个文档,那么您可能希望添加order
调用以确保获得所需的文档。您可以使用and
和or
查询方法而不是单个哈希,但我怀疑它会使事情易于阅读,理解或维护。
我尽量避免使用MongoDB进行OR操作,因为查询会快速失去他们的小脑袋,并且你会留下一些你不想过多想念的恐怖魔法恐怖。您通常最好使用生成的字段预先计算部分查询(您必须维护并进行健全性检查以确保它们是正确的);例如,如果coupon_count
为正数或nil
,则可以添加另一个为真的字段,然后在before_validation
更改时在coupon_count
挂钩中更新该字段。