【问题标题】:search in a text field which contains json在包含 json 的文本字段中搜索
【发布时间】:2017-11-14 06:48:56
【问题描述】:

我的应用程序位于RoR,而数据库位于MYSQL。我有一个User Table。它包含一个字段name。它的类型是文本。 它包含像{"first_name"=> 'Allen', "last_name"=> 'PAul'} 这样的值和一些其他信息。

我可以使用store: accessors: [], coder: JSON 将其存储在数据库中。

现在,我想检索 first_name == 'Allen' 的所有记录。那么如何在rails中实现这一点

【问题讨论】:

  • User.where(:first_name => 'Allen') ?
  • 不,它不会工作
  • ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column
  • 您如何使用 {first_name: 'Allen', last_name: 'PAul'} 存储 name 值?您是否在模型中定义了一个自定义方法以将两者都添加为名称?
  • @NarasimhaReddy:将其写入模型存储:名称,访问者:[:first_name,:last_name],编码器:JSON

标签: mysql ruby-on-rails json


【解决方案1】:

希望这行得通

User.where("name LIKE ?", , '%first_name: #{query}%')

【讨论】:

  • 它可以工作,但需要删除 first_name 后面的空格:
  • 另外,添加引号,如 "first_name":"Allen"
【解决方案2】:

我认为您无法使用经典 ActiveRecord 在 JSON 字段中进行搜索。

但你可以执行原始 sql:

编辑:您的姓名字段必须是 json 字段。

@users = ActiveRecord::Base.connection.execute("SELECT * FROM users WHERE JSON_SEARCH(name, 'all', '#{first_name_to_search}') IS NOT NULL;")

更多信息here

【讨论】:

  • JSON 搜索不存在,我认为只有当我们在 db 中有 json 数据类型时它才有效
【解决方案3】:

问题是用于表示 json 的实际文本表示...

使用

ActiveRecord::Base.connection.execute("SELECT * FROM users")

您可以看到应该如何构建 LIKE 子句以在数据库中找到实际的文本表示。之后就可以使用了

User.find_by_sql("SELECT * FROM users WHERE name LIKE ...") 

进行实际查询

【讨论】:

    【解决方案4】:

    您使用ActiveRecord::Store 重载了name 字段。来自文档:

    Store 为您提供了一个围绕序列化的瘦包装器,用于将哈希存储在单个列中。这就像一个简单的键/值存储在您的记录中当您不关心是否能够在单个记录的上下文之外查询该存储。

    您不能以您所描述的方式使用该字段,并且尝试这样做违背了您正在使用的 API 的目的,因此我建议您不要这样做。您有多种选择:

    1. 使用某种类型的慢查询 (SELECT * FROM User WHERE name LIKE '%foo%') 搜索字段
    2. 实例化所有记录,然后解析它们 (User.all.map { |user| user.name.match(/foo/))
    3. 标准化您的数据库并为您要搜索的每个字段分配适当的字段(name 分为 first_name 和 last_name)

    在这三个选项中,只有 3 是正确的做法。其他两个可能有效,但不应使用,因为它会引入性能和可靠性问题。

    作为使用 3 的奖励,您可以创建一个方法来履行name 的角色:

    class User < ActiveRecord::Base
      def name
        {
          first_name: first_name,
          last_name: last_name
        }
      end
    end
    

    然后您可以按照自己的方式搜索:

    user = User.where(first_name: 'foo').first
    

    并且仍然返回名称:

    user.name
    => { first_name: 'foo', last_name: 'bar' }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      相关资源
      最近更新 更多