【问题标题】:Mongoid Syntax for running range queries with or condition使用 or 条件运行范围查询的 Mongoid 语法
【发布时间】:2016-06-07 20:20:51
【问题描述】:

假设我们需要在 Mongoid 中编写一个范围查询。让要查询的字段为range_field,那么我们这样做

where(:range_field.lte => some-date-time, :range_field.gte => some-date-time)

但如果我想运行查询以选择多个范围中的任何一个,我必须这样做

.or({:range_field.lte => some-date-time1, :range_field.gte => some-date-time2},{:range_field.lte => some-date-time3, :range_field.gte => some-date-time4})

这显然行不通。 如何使用 Mongoid 运行此类查询?

【问题讨论】:

  • “显然不起作用”具体是什么意思?你有错误吗?是不是发现了不该发现的东西?没有找到它应该找到的东西?
  • 它只是运行大于等于查询

标签: ruby-on-rails ruby mongodb mongoid


【解决方案1】:

当你说:

:range_field.lte => some_date_time

您正在调用 lte 的方法,该方法是 Mongoid 猴子在 Symbol 中修补的。该方法返回一个 Origin::Key 实例,该实例包裹在底层 $lte 运算符周围。在 Mongoid 内部的某个地方,Origin::Key 将被转换为 MongoDB 可以理解的东西:

{ range_field: { $lte: some_date_time } }

如果你看什么

where(:range_field.lte => t1, :range_field.gte => t2)

通过在结果上调用selector 得到,你会看到如下内容:

{
  "created_at" => {
    :$gte => t2,
    :$lte => t1
  }
}

一切都会好起来的。

但是,如果我们使用#or 并调用selector 来查看底层查询,我们会看到Mongoid 正在将Origin::Keys 逐一扩展并合并结果:

or({:range_field.lte => t1, :range_field.gte => t2})
# is expanded as though as you said
or({ :range_field => { :$lte => t1 }, :range_field => { :$gte => t2 } })
# which is the same as
or({ :range_field => { :$gte => t2 } })

本质上,Mongoid 在如何扩展Origin::Keys 方面存在不一致。如果您使用:$or 而不是#or,您甚至会得到同样令人困惑的结果:

where(:$or => [ {:range_field.lte => t1, :range_field.gte => t2} ]).selector

会说:

{ "$or" => [ { "range_field" => { "$gte" => t2 } } ] }

解决方案是不使用 Symbol 猴子修补方法并手动完成该部分:

or(
  { :range_field => { :$lte => t1, :$gte => t2 } },
  { :range_field => { :$lte => t3, :$gte => t4 } }, 
  ...
)

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2023-04-08
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多