【问题标题】:Tracking SQL functions in Hasura在 Hasura 中跟踪 SQL 函数
【发布时间】:2021-02-03 22:21:45
【问题描述】:

基本上我正在尝试比较两个 JSONB 行并返回一个数值。但我希望能够查询它。我不确定是否应该使用自定义 SQL 函数、计算字段或 Postgres 生成的列,所以我需要一些建议。

我为每个用户保留了数百个键/值的 jsonb 列:

USERS TABLE:
| username     | user_jsonb_column                          |
|-----------------------------------------------------------|
| 'user1'      |  {"key1":"value1", "key2":"value2" ... }   |
|--------------|--------------------------------------------|
| 'user2'      |  {"key2":"value2", "key3":"value3" ... }   |

我正在尝试用一个非常简单的 SQL 查询来计算 2 个用户的 jsonb 行的相似度:

SELECT ROUND ((

SELECT COUNT(*) from (
    SELECT jsonb_each(user_jsonb_column)
    FROM users WHERE username = 'johndoe'
      INTERSECT
    SELECT jsonb_each(user_jsonb_column)
    FROM users WHERE username = 'janedoe'
)::decimal AS SAME_PAIRS

/ --divide it by

SELECT COUNT(*) from (
    SELECT jsonb_object_keys(user_jsonb_column)
    FROM users WHERE username = 'johndoe'
      INTERSECT
    SELECT jsonb_object_keys(user_jsonb_column)
    FROM users WHERE username = 'janedoe'
  ) as SAME_KEYS

) * 100) as similarity_percentage

这按预期工作,并以百分比形式给出了 2 个 json 对象之间的相似性结果。

我试图把它变成一个函数,这样我就可以查询 2 个用户的相似度百分比:

query {
  calculate_similarity_percentage(
    args: {user1: "johndoe", user2: "janedoe"}
  ){
      similarity_percentage_value
  }
}

但我被困在这一点上,因为我不确定我是否应该考虑trackable custom SQL function(应该返回SETOF <TABLE>,但我需要一个数值),computed field(可以也返回BASE类型),或者在我的情况下可能是Postgres generated column

我一直在阅读 https://hasura.io/docs/1.0/graphql/core/schema/custom-functions.htmlhttps://hasura.io/docs/1.0/graphql/core/schema/computed-fields.html,但我不知道如何解决这个问题,因此我们将不胜感激任何形式的帮助或评论。


更新:是的,正如 Laurenz Albe 指出的,我能够创建这样的函数:

CREATE OR REPLACE FUNCTION public.calculate_similarity_percentage(text, text)
 RETURNS numeric
 LANGUAGE sql
 STABLE
AS $function$

SELECT ROUND(
(select count(*) from (
    SELECT jsonb_each(user_jsonb_column) FROM users WHERE username = $1
    INTERSECT
    SELECT jsonb_each(user_jsonb_column) FROM users WHERE username = $2
    ) as SAME_PAIRS
)::decimal / (
    select count(*) from (
    SELECT jsonb_object_keys(user_jsonb_column) FROM users WHERE username = $1
    INTERSECT
    SELECT jsonb_object_keys(user_jsonb_column) FROM users WHERE username = $2
    ) as SAME_KEYS
    )
    * 100) as similarity_percentage

$function$

那么我就可以执行这个函数了:

SELECT calculate_similarity_percentage('johndoe','janedoe')

它返回这个没有任何问题:

similarity_percentage
62

但是,我希望 Hasura 跟踪这个函数,以便我可以在 graphQL 上查询它:

query MyQuery {
  calculate_similarity_percentage(args: {user1: "johndoe", user2: "janedoe"}) {
    similarity_percentage
  }
}

但是如果我尝试track上面的函数,Hasura 说:

**SQL Execution Failed**
in function "calculate_similarity_percentage":
the function "calculate_similarity_percentage" cannot be tracked for the following reasons:
• the function does not return a "COMPOSITE" type
• the function does not return a SETOF
• the function does not return a SETOF table

我不知道是否可以找到解决方法并将数值作为“COMPOSITE”或 SETOF 表返回。

【问题讨论】:

  • @LaurenzAlbe:对不起,我不够清楚,我用附加部分更新了我的问题。问题是我无法让 Hasura 跟踪该函数,以便它在 graphQL 上公开。

标签: postgresql hasura


【解决方案1】:

这就是我解决问题的方法。但这不是最佳解决方案,所以我不接受这个作为答案。

我最终创建了另一个这样的表:


USER_RELATION_TABLE:
| user1_col   | user2_col  |
|--------------------------|
| 'johndoe'   | 'janedoe'  |
|--------------------------|
| 'brad'      | 'angelina' |
|--------------------------|
|     ...     |     ...    |

然后我使用以下函数在关系表上添加了一个计算域:

CREATE OR REPLACE FUNCTION public.calculate_similarity_percentage(user_relation_row user_relation_table)
 RETURNS numeric
 LANGUAGE sql
 STABLE
AS $function$

SELECT ROUND(
(select count(*) from (
    SELECT jsonb_each(user_jsonb_column) FROM users
    WHERE username = user_relation_row.user1_col
    INTERSECT
    SELECT jsonb_each(user_jsonb_column) FROM users
    WHERE username = user_relation_row.user2_col
    ) as SAME_PAIRS
)::decimal / (
    select count(*) from (
    SELECT jsonb_object_keys(user_jsonb_column) FROM users
    WHERE username = user_relation_row.user1_col
    INTERSECT
    SELECT jsonb_object_keys(user_jsonb_column) FROM users
    WHERE username = user_relation_row.user2_col
    ) as SAME_KEYS
    )
    * 100) as similarity_percentage

$function$

现在我可以像这样在 graphQL 上查询它:

query MyQuery {
  user_relation_table {
    similarity
  }
}

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    相关资源
    最近更新 更多