如何从 postgres JSONB 列中获取值?

Posted

技术标签:

【中文标题】如何从 postgres JSONB 列中获取值?【英文标题】:How get values from postgres JSONB column? 【发布时间】:2019-01-23 23:13:21 【问题描述】:

我有带有 Rails 5 应用程序的 PostgreSQL 10.5 数据库。

我的模特:

# == Schema Information
#
# Table name: property_keys
#
#  id         :integer          not null, primary key
#  name       :string
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  i18n_name  :jsonb
#

class PropertyKey < ApplicationRecord
  # Fields
  store :i18n_name, accessors: I18n.available_locales, coder: JSON
end

我的迁移:

class LocalizeProperties < ActiveRecord::Migration[5.2]
  def up
    add_column :property_keys, :i18n_name, :jsonb

    PropertyKey.all.each do |property_key|
      [:en, :de, :ru].each do |locale_key|
        property_key.i18n_name[locale_key] = property_key.name
      end

      property_key.save!
    end
  end

  def down
    remove_column :property_keys, :i18n_name
  end
end

表名:property_keys。字段列表:

id:大整数 i18n_name: jsonb

这是对所有数据的请求:

我想获取所有英文名称("en" 键在 i18n_name 列中的值)。

这是一个请求:

SELECT
    id,
    i18n_name,
    i18n_name->'en' AS en
FROM property_keys;

它什么也不返回。

但理论上应该返回填充“en”列的数据。

这是截图:

我还尝试使用-&gt;&gt; 进行查询,但没有成功:

我应该如何更改我的请求以及我应该使用哪个PostgreSQL operators 来使其正常工作?

检查的 JSONB 列的长度:

【问题讨论】:

尝试使用-&gt;&gt; 运算符? 从简化的自治示例开始,例如 with t(x) as (values('"en":"a","de":"b","ru":"c"'::jsonb)) select x, x-&gt;'en' from t; 如果它对你有用(它应该)然后尝试找出差异。 @Abelisto 查询 with t(x) as (values('"en":"a","de":"b","ru":"c"'::jsonb)) select x, x-&gt;'en' from t; 有效! 好的,有调试模板:dbfiddle.uk/… 只需使用您的表/列名而不是 CTE。请注意,JSONB 对象中的“bе”键包含西里尔字母“е”,因此其十六进制表示不同。 @bmalets 告诉你有些字符是你看不到的。如果没有这样的密钥,您将无法提取 en 密钥。你的答案就在那里。调查数据以查看其中的内容或通过运行更新来修复它 【参考方案1】:

-&gt;-&gt;&gt; 运算符按预期工作,通过键或在后一种情况下作为文本检索 json 对象。

我怀疑您遇到的真正问题是,您看到的数据并不是存储在表中的数据,这就是为什么 i18_name-&gt;'en' 无法工作,因为没有密钥 en

为了能够确认我的写作,请在下面运行查询以查看您在字符串中看到的内容的长度和存储在表中的内容是否匹配。他们可能不会:

select
  length(i18n_name::text) AS stored,
  length('"en":"asdasdadad","de":"asdasdadad","ru":"asdasdadad"') AS whatisee

你能用它做什么?使用bytea 数据类型转换来调查数据,或者只是UPDATE 在此列中包含正确(您所看到的)数据的行。

这将使运营商带来您真正期望的东西,因为 jsonb 字段中会有 en 键。

【讨论】:

【参考方案2】:

你需要the -&gt;&gt; operator:

SELECT id,
       i18n_name,
       i18n_name->>'en' AS en
  FROM property_keys;

【讨论】:

只是好奇:为什么你认为-&gt;&gt; 运算符可以在-&gt; 运算符不工作的地方工作? 很遗憾,我没有工作...我附上PgAdmin查询的截图【参考方案3】:

就我而言,在 psql 11 中,-&gt;-&gt;&gt; 都适用于 json 和 jsonb 对象。

-&gt; 获取带双引号 ("") 的值,-&gt;&gt; 获取不带双引号的值。

【讨论】:

以上是关于如何从 postgres JSONB 列中获取值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Slick 在 Postgres 中将 json 对象插入到 jsonb 类型的列中

如何仅从 postgres 获取特定键的 jsonb?

使用 Postgres/Knex 在 JSONB 列中存储对象

postgres jsonb列中的模糊字符串匹配

如何在 postgres 中对 jsonb 值求和?

如何将postgres jsonb字段的属性插入键值表?