微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何编写迁移以将 JSON 字段转换为 Postgres 数组以在 Rails 中查询?

如何解决如何编写迁移以将 JSON 字段转换为 Postgres 数组以在 Rails 中查询?

一个旧表,列类型为 JSON,但此列中仅存储数组。 即使我正在存储数组,我也无法使用 ANY 关键字查询此字段(这将适用于 Postgres 中的数组类型列,例如 post

例如:假设 ['Apple','Orange','Banana'] 在 fruits 列中存储为 Json,我想像 Market.where(":name = ANY(fruits)",name: "Orange") 一样查询并让所有市场上都有可用的橙子。

谁能帮我写一个迁移来将现有列(类型:Json)更改为数组类型?

解决方法

假设一个 json 字段的示例:

\d json_test 
               Table "public.json_test"
  Column   |  Type   | Collation | Nullable | Default 
-----------+---------+-----------+----------+---------
 id        | integer |           |          | 
 fld_json  | json    |           |          | 
 fld_jsonb | jsonb   |           |          | 
 fruits    | json    |           |          | 

insert into json_test (id,fruits) values (1,'["Apple","Orange","Banana"] ');
insert into json_test (id,fruits) values (2,'["Pear",fruits) values (3,"Apple","Banana"] ');

WITH fruits AS 
(SELECT 
    id,json_array_elements_text(fruits) fruit 
 FROM json_test) 
SELECT 
   id 
FROM 
   fruits
WHERE 
    fruit = 'Orange';
 id 
----
  1
  2

UPDATE JSON数组转Postgres数组的方法:

SELECT 
    array_agg(fruit) 
FROM 
    (SELECT 
        id,json_array_elements_text(fruits)AS fruit 
    FROM 
    json_test) AS elements 
GROUP BY 
    id;

 array_agg       
-----------------------
 {Pear,Apple,Banana}
 {Pear,Orange,Banana}
 {Apple,Banana}

这假设 JSON 数组具有同构元素,因为这是 Postgres 数组的要求。

查找 json 字段中包含“橙色”的行的更简单方法:

SELECT 
    id,fruits 
FROM 
    json_test 
WHERE 
    fruits::jsonb ? 'Orange';

 id |             fruits             
----+--------------------------------
  1 | ["Apple","Banana"] 
  2 | ["Pear","Banana"] 

,
class AddArrayFruitsToMarkets < ActiveRecord::Migration[6.0]
  def up
    rename_column :markets,:fruits,:old_fruits
    add_column :markets,:string,array: true
    Market.update_all('fruits = json_array_elements(old_fruits)')
  end
end
class RemoveJsonFruitsFromMarkets < ActiveRecord::Migration[6.0]
  def up
    remove_column :markets,:old_fruits
  end
end

但真的如果您要做某事,为什么不创建表格,因为您并没有真正改进任何东西?

class Fruit < ApplicationRecord
  validates :name,presence: true
  has_many :market_fruits
  has_many :markets,through: :market_fruits
end

class MarketFruit < ApplicationRecord
  belongs_to :market
  belongs_to :fruit
end

class Market < ApplicationRecord
  has_many :market_fruits
  has_many :fruits,through: :market_fruits

  def self.with_fruit(name)
    joins(:fruits)
      .where(fruits: { name: name })
  end

  def self.with_fruits(*names)
    left_joins(:fruits)
      .group(:id)
      .where(fruits: { name: names })
      .having('COUNT(fruits.*) >= ?',names.length) 
  end
end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。