find_by 和 json 数组使用 IN 执行查询而不是搜索整个数组

find_by with json array executing a query with IN instead of searching for the whole array

我有一个带有 jsonb 字段(坐标)的模型(区域):

  create_table "areas" do |t|
    t.jsonb "coordinates"
  end

现在如果我插入一个数组:

Area.create(coordinates: [1, 2])

它工作正常,但正在搜索它:

Area.find_by(coordinates: [1, 2])

使用 IN 执行 SQL 查询,例如:

SELECT "areas".* FROM "areas" WHERE "areas"."coordinates" IN (, ) LIMIT   [["coordinates", "1"], ["coordinates", "2"], ["LIMIT", 1]]

我尝试搜索 [[1, 2]][[[1, 2]]],但我总是得到 IN 查询。

(可能是 rails 问题)

这是您要找的吗?

Area.find_by("coordinates = '[1, 2]'")

查询 JSON/Array/Hstore 类型的列时必须使用 SQL 字符串。例如:

Event.where("payload->>'kind' = ?", "user_renamed")

它们不是查询界面的 "native" 部分,因为由于键入和不同的实现,创建查询比普通列要复杂得多。 ActiveRecord 只会为这些类型创建查询,就好像它在它理解的普通列类型中一样。参见 Active Record and PostgreSQL

查询 json 列中的数组可以通过以下方式完成:

WHERE coordinates @> ANY (ARRAY [1,2,3]::jsonb[]);

但是 - 也许您应该重新考虑使用 JSON 列是否是一个好主意,因为查询会很糟糕? JSON/JSONB 类型适用于某些特殊任务,在这些任务中数据不符合模式,但不应替代正确的关系数据库建模。不必要 JSONB 是反模式。

此外,如果这些是地理坐标,则您将这些数字表示为整数或浮点数,但除了添加 . 之外,无法在 JSON 中指定类型,解析器如果2.0 是浮点数或整数。

如果您为坐标设置单独的 table,您实际上可以使用和使用 ActiveRecord 关联,并具有一定程度的数据规范化、索引、引用完整性等。哦,我有没有提到你实际上可以像一个正常人一样查询你的数据?

class Area
  has_many :coordinates
end

# rails g model coordinate area:references lat:decimal lng:decimal
class Cooridinate
  belongs_to :area
end


Area.joins(:coordinates).where(coordinates: { lat: 1, lng: 1 })

您还可以使用 PostGIS extension,它为坐标、多边形和其他类型的地理信息提供专门的列类型。