[英]How to write a migration to convert JSON field to Postgres Array for querying in rails?
There is an old table with column type as JSON but only arrays are stored in this column.有一个列类型为 JSON 的旧表,但只有 arrays 存储在此列中。 Even though I am storing array, I am not able to query this field using the ANY
keyword (which will work on array type columns in Postgres like in this post )即使我正在存储数组,我也无法使用ANY
关键字查询该字段(这将适用于 Postgres 中的数组类型列,如本文中所示)
Eg : let's say ['Apple', 'Orange', 'Banana'] is stored as Json in the fruits
column, I want to query like Market.where(":name = ANY(fruits)", name: "Orange")
and get all the markets with Oranges available.例如:假设 ['Apple', 'Orange', 'Banana'] 在fruits
列中存储为 Json,我想查询Market.where(":name = ANY(fruits)", name: "Orange")
并获得所有可用橙子的市场。
Can anyone please help me to write a migration to change the existing column(type: Json) to array type?谁能帮我写一个迁移来将现有的列(类型:Json)更改为数组类型?
One example assuming a json
field:一个假设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", "Orange", "Banana"] ');
insert into json_test (id, fruits) values (3, '["Pear", "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 Method to convert JSON array into Postgres array:将 JSON 数组转换为 Postgres 数组的UPDATE方法:
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,Orange,Banana}
This assumes the JSON array has homogeneous elements as that is a requirement for Postgres arrays.这假设 JSON 数组具有同质元素,因为这是 Postgres arrays 的要求。
A simpler method of finding rows that have 'Orange' in the json
field:在json
字段中查找具有“橙色”的行的更简单方法:
SELECT
id, fruits
FROM
json_test
WHERE
fruits::jsonb ? 'Orange';
id | fruits
----+--------------------------------
1 | ["Apple", "Orange", "Banana"]
2 | ["Pear", "Orange", "Banana"]
class AddArrayFruitsToMarkets < ActiveRecord::Migration[6.0]
def up
rename_column :markets, :fruits, :old_fruits
add_column :markets, :fruits, :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
But really if you're going to do something why not create tables instead as you're not really improving anything?但是,如果您真的要做某事,为什么不创建表格,因为您并没有真正改进任何东西?
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.