Поиск полей jsonb в postgresql с помощью Hasura

Можно ли выполнить поиск больше, чем поиск по полю jsonb, используя hasura?

это кажется возможным в самом PostgreSQL, Как сделать меньше, больше, чем в полях JSON Postgres?

в postgres я храню таблицу

актив

  • имя: строка
  • версия: инт
  • метаданные: jsonb

метаданные выглядят так.

{'длина': 5}

Я могу найти asset, который точно соответствует, используя _contains.

{
  asset(where:{metadata : {_contains : {length: 5}}}){
    name
    metadata
  }
}

Я хотел бы иметь возможность найти asset длиной более 10.

Я старался:

{
  asset(where:{metadata : {_gt : {length: 10}}}){
    name
    metadata
  }
}

person com48    schedule 25.07.2021    source источник


Ответы (1)


A. Possibility to do on graphql level directly

Документация Hasura: операторы JSONB (_contains, _has_key и т. д.) упоминает только 4 оператора:

Операторы _contains, _contained_in, _has_key, _has_keys_any и _has_keys_all используются для фильтрации на основе столбцов JSONB.

Итак, прямой ответ на ваш вопрос: Нет. Это невозможно сделать на уровне graphql в хасуре.

(По крайней мере, пока это невозможно. Кто знает: возможно, в будущих версиях будет реализовано больше операторов. )

B. Using derived views

Но есть и другой способ, описанный в https://hasura.io/blog/postgres-json-and-jsonb-type-support-on-graphql-41f586e47536/#derived-data

Эта рекомендация повторяется в: https://github.com/hasura/graphql-engine/issues/6331

У нас нет таких операторов для JSONB (может быть решено чем-то вроде # 5211), но вы можете использовать представление или вычисляемое поле, чтобы свести текстовое поле из столбца JSONB в новый столбец, а затем сделать то же самое.

Рецепт:

<сильный>1. Создать представление

CREATE VIEW assets -- note plural here. Name view accordingly to your style guide
AS
SELECT
      name, 
      version,
      metadata,
      (metadata->>'length')::int as meta_len  -- cast to other number type if needed
   FROM asset

<сильный>2. Зарегистрировать это представление

<сильный>3. Используйте его в запросах graphql как обычную таблицу

E.g.

query{
  assets(where: {meta_len: {_gt:10}}){
   name
   metadata
}

C. Using SETOF-functions

<сильный>1. Создать SETOF-функцию

CREATE FUNCTION get_assets(min_length int DEFAULT 0)
RETURNS SETOF asset
LANGUAGE SQL
STABLE
AS $$
SELECT * FROM asset
WHERE
  (metadata->>'length')::int > min_length;
$$;

<сильный>2. Зарегистрируйтесь в хасуре

<сильный>3. Использовать в запросах

query{
  get_assets(args: {min_length: 10}){
   name
   metadata
}

Думаю, это был последний возможный вариант.

Это не даст вам полной свободы без схемы, которую вы, возможно, ищете, но IDK знает о других способах.

person Alex Yu    schedule 26.07.2021
comment
Привет Алекс, Спасибо за ваш ответ, к сожалению, я не знаю заранее, какие записи будут в метаданных и что можно искать. поэтому для моего варианта использования я не могу заранее создать представление. - person com48; 26.07.2021
comment
@ com48 У нас была такая же проблема, и мы хотели бы иметь решение и на уровне graphql. Сейчас его просто нет в хасуре. На самом деле есть третий способ, который мы используем в основном: расширение с помощью функций, но это опять же не даст вам полной бессхемной свободы — подумайте сами, нужен ли вам такой уровень свободы? - person Alex Yu; 26.07.2021