【问题标题】:Querying a mysql json array against another array in ActiveRecord针对 ActiveRecord 中的另一个数组查询 mysql json 数组
【发布时间】:2020-01-21 18:51:23
【问题描述】:

我正在尝试查询 mysql 数据库。我只需要返回外部数组中存在的值:

query_data = tours.select(:orders)

=> [#<Tour:0x007fd1b0972438 orders: [223597]>, ...]

我有一个如下所示的外部数组:orders = [223597, 223598]

现在,我正在使用 ruby​​ 来过滤数据,但它并没有我想要的那么高效:

query_data = query_data.find_all do |data|
  data.orders.any? { |o| orders.include?(o) }
end

所以我的问题是,我怎样才能检查数据库数组和订单数组,并且只返回那些 ID 存在于数据库数组中的记录,只使用 SQL?

我正在尝试这样的事情,但我认为这不是正确的做法:

query_data.where("JSON_EXTRACT('tour.orders', '$[*]') IN #{orders}")

另外,它只是直接不起作用。

版本:

Ruby: 2.3.1
mysql: mysql  Ver 14.14 Distrib 5.7.29, for osx10.14 (x86_64) using  EditLine wrapper
Rails: 5

【问题讨论】:

    标签: mysql ruby activerecord ruby-on-rails-5


    【解决方案1】:

    在 SQL 查询的 WHERE 子句中使用 JSON_EXTRACT() 可以保证它不能使用索引。所以它会进行表扫描,但效率并不高。

    一般来说,我向在数据库中有 JSON 列的开发人员推荐:

    您可以在 SELECT-list 中提取 JSON 文档的一部分:

    SELECT JSON_EXTRACT(tour.orders, '..expr..') FROM ...
    

    但不要在 SQL 查询的任何其他子句中这样做。不在 WHERE 子句中,也不在 JOIN 表达式中,或在 GROUP BY、ORDER BY、HAVING 等中。有很多情况无法优化,它使您的 SQL 查询超级复杂,难以编码,难以阅读,并且难以维护。

    相反,如果您想与 JSON 数组的各个元素进行比较,您应该以标准化方式将它们存储在子表中,每行一个项目。

    例如,您可能有一个表 tour_orders,其中每一行都引用了 tour.id 和一个订单 ID。然后你可以用更易读的方式查询它:

    query_data.where(order: orders)
    

    在 MySQL 中使用 JSON 数据类型可以轻松插入大量数据,但会使许多类型的查询变得更加困难。如果您需要 SQL 表达式来访问 JSON 文档的各个元素,我建议避免使用 JSON 数据类型。

    【讨论】:

    • 是的...我希望我能够重新设计数据库。暂时可能不得不坚持使用红宝石解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2020-10-06
    • 1970-01-01
    相关资源
    最近更新 更多