【发布时间】: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.html 和 https://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