【问题标题】:mongoid: Rails says field exists, mongodb says contrarymongoid:Rails 说字段存在,mongodb 说相反
【发布时间】:2021-09-19 15:17:40
【问题描述】:

我有一组复杂的文档。

{
<some fields>,
meta_info: {
   company_name: String,
   invalid: Boolean,
   mobile_layout: String,
   <more fields>
  }
<lots more fields>
}

我让 Rails 使用 meta_info.invalid 为 true/false/nil 找到所有那些文档

finished_acts.where('meta_info.invalid' => true/false/nil)

现在有一个文档,其中该字段不存在。请问……

finished_acts.find('meta_info.invalid' => {'$exists' => false})
 => nil

这完全是不真实的(另外,如果我问{'$exists' =&gt; true},它也会产生 nil),也是如此

finished_acts.where('meta_info.invalid' => {'$exists' => false}).count
 => 0

我怎样才能找到这份文件?我花了几天时间收集统计数据,与数据库本身提供的信息相比,这些数据总是相差一个计数,原因是这个不存在的字段。

我正在使用 mongoDB V3.4.17 和 Mongoid 6.1.0。

编辑:后来我了解到我错误地使用了.find 命令,它仅用于_id 字段并且不接受JSON/哈希。

我的问题显然显示了 Mongoid 的 Active Record 适配的实现中的一个错误,我正在慢慢地将我的代码转换为始终使用聚合。这样做时,我得到了正确数量的文档。当然,聚合返回的结构处理起来更复杂,因为它只有哈希和数组,但如果这是为了获得正确结果而进行的权衡,我很满意。

【问题讨论】:

  • $exists: false 适用于嵌套字段:mongoplayground.net/p/be8sVcdQU8g。 ruby/mongoid 不应该搞砸了,但还是尝试使用 mongodb cli 进行查询
  • 顺便说一句,我知道我可以通过聚合来做到这一点,但这会产生一组难以操作的文档。我想使用 Mongoid 提供的模型。
  • @SergioTulentsev 抱歉,我知道如何使用 mongo。我想知道如何使用 Mongoid。我有一个 Rails 程序,它需要找到正确的结果集。
  • 那么,让我们看看 mongoid 生成的查询。我很好奇,会有什么不同。

标签: ruby-on-rails mongoid


【解决方案1】:

不要依赖 Mongoid 中的 ActiveRecord 适配;使用聚合管道。这将(据我所知)总是返回正确的结果,因为它只是将参数散列推入 mongo。

聚合管道一开始使用起来似乎不直观,但在您知道如何使用它之后,如果您想进行复杂的查询,它是一个非常强大的工具。 Rails 语法如下:

MyClassName.collection.aggregate( <array> )

其中&lt;array&gt; 包含散列,每个散列都是用于执行前一个散列的结果的命令。可以在https://docs.mongodb.com/manual/aggregation/ 找到该文档。 要将那里的命令转换为 Ruby,只需将条目用引号括起来。

举个例子:下面是mongo的语法:

db.orders.aggregate([
  { $match: { status: "A" } },
  { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])

这会从orders 集合中获取所有文档,并选择所有状态字段与“A”匹配的文档(冒号左侧的单词$match 是一个mongo 命令)。然后将它们按cust_id 字段分组($group),并计算amount 字段内容的总和($sum)。 如果你想把它转换成 Ruby,你把它改成

Orders.collection.aggregate([
      { '$match': {'status': 'A'}},
      { '$group': {'_id': '$cust_id', 'total': {'$sum': '$amount'}}}
   ])

这对我有用,更好的是它比在 Rails 中使用 Orders.where(...) 并在 Rails 中进行计算花费的时间明显少。 权衡是您不会得到返回的 Ruby 对象,而是哈希数组的哈希值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多