Не удалось создать эффективную базовую мутацию с отношениями с использованием Hasura и GraphQL

#graphql #hasura

#graphql ( графический sql ) #hasura #graphql

Вопрос:

Я создаю API поверх моей базы данных PostgreSQL, используя Hasura и GraphQL в качестве среднего уровня.

Я управляю сервисным бизнесом, где клиенты могут подписаться на такие услуги, как «еженедельная чистка кофемашины» или «пополнение буфета для мохито». Клиент может подписаться на одну и ту же услугу только один раз.

Мы являемся организацией, ориентированной на продажи, поэтому у нас есть разные приложения, в которые люди могут добавлять (customer, subscription) комбинации. Нам нужна конечная точка, которая принимает эту (customer, subscription) комбинацию и заботится о таких деталях, как вставка, customer если она не существует.

Сначала мы попытались использовать следующую мутацию против Hasura:

 mutation InsertOrders {
  insert_orders(objects: [
    { 
      customer: {data: {name: "GE"}}, 
      subscription:  {data: {name: "Coffee Refill"}}
    }
  ]) 
  {
    affected_rows
  }
}
  

Эта операция выполняется успешно, только если "GE" не является существующим клиентом и "Coffee Refill" не является существующей подпиской.
Затем мы попытались использовать "on_conflict" функциональность в Hasura:

 mutation InsertOrders {
  insert_orders(objects: [
    { 
      customer: {data: {name: "GE"}, 
        on_conflict: { constraint:customers_name_unique , update_columns:[name] }
      }, 
      subscription:  {data: {name: "Coffee Refill"},
        on_conflict: { constraint:subscriptions_name_unique , update_columns:[name] }
      }
    }
  ]) 
  {
    affected_rows
  }
}
  

Такой способ работает, но у него есть несколько недостатков:

  1. Он обновляет строку клиента (или подписки), если клиент существует, фактически обновление без операции. Это также обновляет потенциальный updated_at столбец.
  2. Это неэффективно (см. 1.). У нас крошечная база данных (сотни строк), и время ожидания нашей попытки вставить около 50 (customer, subscription) комбинаций в один запрос истекло.

Определение базы данных здесь:

 CREATE TABLE customer (
  id UUID PRIMARY KEY, 
  name VARCHAR(50) UNIQUE
);

CREATE TABLE subscription (
  id UUID PRIMARY KEY,
  name VARCHAR(50) UNIQUE
);

CREATE TABLE orders (
  customer UUID REFERENCES customer (id),
  subscription UUID REFERENCES subscription (id),
  PRIMARY KEY (customer, subscription)
)
  

Комментарии:

1. Чтобы проигнорировать обновление, вы должны оставить update_columns пустым. Что-то вроде { on_conflict: { constraint:products_name_unique , update_columns:[] } }

2. @LeonardoAlves Спасибо вам за ваш вклад. Я пробовал это, но получаю ошибку cannot proceed to insert object relation "subscription" since insert to table "subscription" affects zero rows . Это упоминается в разделе «Вложенные предупреждения о вводе» в документации Hasura

3. простота использования приложения не должна приводить к плохому дизайну БД… одно действие в приложении может привести к нескольким последовательным действиям под капотом (обновить / обновить клиента, создать продукт, использовать результаты для вставки заказа — для накладной скопируйте данные пользователя / продукта, а не только свяжите их) … заказ [строка] не должен содержать прямого отношения к продукту (нет согласованности — изменение продукта влияет на более ранние отношения)