Ruby on Rails中查询JSON类型字段仅返回指定键的方法
Ruby on Rails 构造JSON字段单键查询的方法
Rails没有提供跨数据库统一的JSON字段单键提取封装,需要结合你使用的数据库原生JSON操作函数实现,核心是在查询时通过select指定只提取目标键,避免把整个JSON字段全量加载到内存。
以下是基于你给出的ActivityPart模型,提取activity_json字段中image键值的具体实现:
按数据库类型选择写法
PostgreSQL(Rails最常用的生产数据库)
PostgreSQL提供了->>(返回文本格式值)、->(返回JSON格式值)两个操作符提取JSON键,写法如下:
# 查询时指定提取image键,起别名方便后续读取 activity_parts = ActivityPart.select( :id, :activity_type, :created_at, "activity_json->>'image' as activity_image" ) # 读取结果时直接调用别名属性即可 activity_parts.each do |part| puts part.activity_image # 拿到的就是activity_json里image对应的内容 end
如果image键对应的值是嵌套的JSON结构,把->>换成->即可,返回值会保留JSON类型。
MySQL 5.7+
MySQL可以用JSON_EXTRACT函数或者等价的->>简写语法提取JSON键:
# 完整函数写法 activity_parts = ActivityPart.select( :id, :activity_type, "JSON_UNQUOTE(JSON_EXTRACT(activity_json, '$.image')) as activity_image" ) # 简写写法,效果和上面完全一致 # activity_parts = ActivityPart.select(:id, :activity_type, "activity_json->>'$.image' as activity_image")
常用扩展场景
- 带查询条件的写法:正常追加
where条件即可,不影响JSON字段提取逻辑# 例:只查询activity_type为"topic"的记录的image值 topic_images = ActivityPart .where(activity_type: 'topic') .select(:id, "activity_json->>'image' as activity_image") - 只需要拿到值数组不需要模型实例时,用
pluck性能更高:# PG环境直接拿到所有image值组成的数组,跳过模型实例化 all_images = ActivityPart.pluck(Arel.sql("activity_json->>'image'"))
注意事项
- 提取的JSON键一定要起别名,否则Rails无法给返回的模型实例挂载对应属性,你读不到目标值
- 不要先把整个
activity_json字段全查出来再在Ruby代码里取activity_json['image'],数据量大时会造成不必要的内存和带宽浪费 - 如果指定键不存在,数据库会返回
NULL,对应到Ruby层面就是nil,和Hash取不存在键的行为一致
内容的提问来源于stack exchange,提问作者jamal
相关产品推荐
相关产品推荐

