如何在Postgres中执行JSON/JSONB的形状?

发布于 2025-02-02 12:30:30 字数 289 浏览 3 评论 0原文

我试图在JSON中存储对调查问题的回答,因为它们可能在布尔值(这是栏?是/否),数字(foo?),字符串(描述什么是foo)。它运行良好,但是我该如何执行某个问题,JSON的形状相同?

例如,对于“您每天要吃多少个Foo或酒吧?”的问题, 我期望以下结构(假设它是列答案):

{
 "foo": "number",
 "bar": "number"
}

我该如何执行并保持数据一致?

I am trying to store the response to questions of a survey in JSON, as they could be in boolean(Is this Bar? Yes/No), number(How much is Foo?), string(Describe what is Foo). It is working fine, but how can I enforce that for a certain question, the JSON will be of identical shape?

For example, for the question "How many Foo or Bar do you eat everyday?",
I am expecting the following structure(let's say it is column answer):

{
 "foo": "number",
 "bar": "number"
}

How can I enforce that and keep my data consistent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

束缚m 2025-02-09 12:30:30

这样做的“正确”方法是使您的数据正常化或在应用程序级别执行模式。

Postgres JSON是毫无用处的。这个想法是,如果您的数据结构化,则可能应在普通列中。但是,在数据结构但架构是动态的情况下,JSON是一个完全有效的选择。在这种情况下,最好在应用程序层执行模式约束。

There 'right' way yo do this is either to normalize your data or to enforce schema at the application level.

Postgres JSON is delibrately schemaless. The idea is that if your data is structured it should probably be in normal columns. However, JSON is a totally valid option in the situation where the data is structured but the schema is dynamic. In those situations it's best to enforce schema constraints at the application layer.

还在原地等你 2025-02-09 12:30:30

通常,这个话题是广泛而复杂的。对于那些有兴趣的人,我建议 json Schema 网站。

出于我们的目的,我们可以使用一种非常简单的验证方法,仅限于两个问题,在功能体系中发表了评论:

create or replace function validate_answer(answer jsonb, pattern jsonb)
returns bool language plpgsql as $
declare
    rec record;
begin
-- does the answer contain exactly the same keys as the pattern?
    if not (
        select array_agg(keys_ans) = array_agg(keys_pat)
        from (
            select 
                jsonb_object_keys(answer) as keys_ans, 
                jsonb_object_keys(pattern) as keys_pat
            ) s
        ) then return false;
    end if;

-- are the value types of all keys the same in the answer and pattern?
    for rec in
        select *
        from jsonb_each(pattern)
    loop
        if jsonb_typeof(answer->rec.key) <> jsonb_typeof(rec.value)
        then return false;
        end if;
    end loop;
    return true;
end $;

db&lt;&gt; fiddle。

如您所见,该模式只是一个格式良好的答案的一个示例。为每个问题定义一个模式,为答案表创建一个触发器,然后在触发函数中使用上述函数来验证新的或修改的答案。

In general, the topic is extensive and complex. For those interested, I recommend the JSON Schema website.

For our purposes, we can use a very simple method of validation, limited to two issues, commented in the function body:

create or replace function validate_answer(answer jsonb, pattern jsonb)
returns bool language plpgsql as $
declare
    rec record;
begin
-- does the answer contain exactly the same keys as the pattern?
    if not (
        select array_agg(keys_ans) = array_agg(keys_pat)
        from (
            select 
                jsonb_object_keys(answer) as keys_ans, 
                jsonb_object_keys(pattern) as keys_pat
            ) s
        ) then return false;
    end if;

-- are the value types of all keys the same in the answer and pattern?
    for rec in
        select *
        from jsonb_each(pattern)
    loop
        if jsonb_typeof(answer->rec.key) <> jsonb_typeof(rec.value)
        then return false;
        end if;
    end loop;
    return true;
end $;

Test the function in Db<>Fiddle.

As you can see, the pattern is just an example of a well-formatted answer. Define a pattern for each question, create a trigger for the answers table and use the above function inside the trigger function to verify new or modified answers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文