SlideShare a Scribd company logo
ORM vs GraphQL
Oleksandr Tarasenko
EVO.company / prom.ua
Agenda
● Raw SQL in python
● Python ORM libs
● async/await and ORM solutions
● GraphQL implementation
2
WHY?
3
4
5
6
GraphQL
Raw SQL in python
import psycopg2
class pg_conn:
def __enter__(self):
self.conn = psycopg2.connect(
dbname='fwdays', user='highload'
)
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if hasattr(self, 'conn'):
self.conn.close()
7
with pg_conn() as db:
cur = db.cursor()
query = "insert into product('name') values('toy')"
cur.execute(query)
db.commit()
cur.close()
db.close()
Raw SQL in python
● psycopg2
● written in C
● implementation of the DB API 2.0 (PEP 249)
● works like a libpq wrapper
8
Raw SQL in python
● psycopg2
● written in C
● implementation of the DB API 2.0 (PEP 249)
● works like a libpq wrapper
9
Raw SQL in python
import psycopg2
class pg_conn:
def __enter__(self):
self.conn = psycopg2.connect(
dbname='fwdays', user='highload'
)
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if hasattr(self, 'conn'):
self.conn.close()
10
with pg_conn() as db:
cur = db.cursor()
query = "insert into product('name') values('toy')"
cur.execute(query)
db.commit()
cur.close()
db.close()
Raw SQL in python
insert into products('name') values('toy');
11
Raw SQL in python
insert into products('name') values('toy');
select settings from application_settings
where company_id in (
3244414, 3239428, 3246756, 3215974
);
12
Raw SQL in python
13
select csa.company_id, count(csa.id)
from company_site_attributes as csa
join company as c on c.id = csa.company_id
join site_filters as csf on csf.attribute_id = csa.id
where portal_attribute_id in (1536, 17536) and
c.premium_service_id > 0 and
csa.status = 0 and
csf.status = 0
group by csa.company_id, csa.id
having count(csa.id) > 1;
Raw SQL in python
14
select csa.company_id, count(csa.id)
from company_site_attributes as csa
join company as c on c.id = csa.company_id
join site_filters as csf on csf.attribute_id = csa.id
where portal_attribute_id in (1536, 17536) and
c.premium_service_id > 0 and
csa.status = 0 and
csf.status = 0
group by csa.company_id, csa.id
having count(csa.id) > 1;
Raw SQL
● small tables
15
Raw SQL
● small tables
● few tables
16
Raw SQL
● small tables
● few tables
● no complicated types
17
Raw SQL
● small tables
● few tables
● no complicated types
● no need to manage scheme in the app
18
Raw SQL
● small tables
● few tables
● no complicated types
● no need to manage scheme in the app
● no migrations
19
Raw SQL
● small tables
● few tables
● no complicated types
● no need to manage scheme in the app
● no migrations
● no dynamic queries
20
Raw SQL
● small tables
● few tables
● no complicated types
● no need to manage scheme in the app
● no migrations
● no dynamic queries
● no app session managing
● ...
21
Python ORM
22
Python ORM
● SQLAlchemy
● Django ORM
● Peewee
● Pony ORM
● Tortoise ORM
● SQLObject
● GINO *
● ...
23
Python ORM +
● Scalability
● Security
● Trust
● Time
24
Python ORM -
● Speed
● Scope
25
Oleksandr Tarasenko "ORM vs GraphQL"
SQLAlchemy
● SQLAlchemy Core
● SQLAlchemy ORM
27
28
29
30
31
32
Oleksandr Tarasenko "ORM vs GraphQL"
Oleksandr Tarasenko "ORM vs GraphQL"
SQLAlchemy -> asyncio
● psycopg ?
SQLAlchemy -> asyncio
● psycopg ?
AsyncIO vs SQLAlchemy
https://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/
SQLAlchemy -> asyncio
● psycopg
● aiopg
● asyncpg
aiopg vs asyncpg
https://www.youtube.com/watch?v=bY6ZU0-26TA
aiopg
psycopg
libpq
pgbouncer
postgres
asyncpg
pgbouncer
postgres
41
GraphQL
GraphQL in Python
● Graphene
● Ariadne
● Strawberry
● Hiku
Graphene
from graphene import ObjectType, String, Schema
class Query(ObjectType):
name = String(description='Name field')
formated_price = String(description='Price field')
def resolve_name(self, info):
name = get_product_name()
...
return name
def resolve_price(self, info):
price = get_product_price()
...
return format_price(price)
schema = Schema(query=Query)
query = '''
query Products {
name
price
}
'''
result = schema.execute(query)
Graphene
Base = declarative_base()
Base.query = db_session.query_property()
class ProductModel(Base):
__tablename__ = 'product'
id = Column(Integer, primary_key=True)
name = Column(String)
price = Column(Integer)
class Product(SQLAlchemyObjectType):
class Meta:
model = ProductModel
interfaces = (relay.Node, )
class Query(ObjectType):
node = relay.Node.Field()
products = SQLAlchemyConnectionField(Product)
schema = Schema(query=Query, types=[Product, ])
Graphene
query = '''
{
products {
edges {
node {
name
price
}
}
}
}
'''
Ariadne
from ariadne import ObjectType, QueryType, gql,
make_executable_schema
from ariadne.asgi import GraphQL
type_defs = gql("""
type Query {
products: [Product!]!
}
type Product {
id: Int
name: String
price: Int
}
""")
query = QueryType()
@query.field("products")
def resolve_products(*_):
...
return get_products_from_db()
product = ObjectType("Product")
@product.field("name")
def resolve_product_name(product, *_):
...
return get_product_name_from_db()
schema = make_executable_schema(type_defs, query,
product)
app = GraphQL(schema, debug=True)
Ariadne with ORM
https://github.com/mirumee/ariadne/issues/115
Hiku
from hiku.graph import Graph, Node, Link, Field, ...
from hiku.sources import sqlalchemy as sa
from hiku.types import Boolean, Integer, String, TypeRef, ...
product_query = sa.FieldsQuery('db.session', Product.table)
# product_query = asyncsa.FieldsQuery('db.session_async', Product.table)
low_level_graph = Graph([
Node('Product', [
Field('id', Integer, product_query),
Field('name', String, product_query),
Field('price', None, product_query),
...
])
query = '''
product(ids: [1234, 1235]) {
id
name
price
}
'''
"""
SELECT id, name, price FROM product
WHERE id IN (:id1, :id2, ..., :idN)
"""
Hiku
low_level_graph = Graph([
Node('Product', [
Field('id', Integer, product_query),
...
Link(
'discount',
Optional[TypeRef['Discount']],
product_to_discount_query,
requires='id',
),
]),
Node('Discount', [
Field('id', Integer, discount_query),
Field('amount', Integer, discount_query),
])
])
discount_query = sa.FieldsQuery('db.session', Discount.__table__)
"""
SELECT id, name, price, price_currency_id FROM product
WHERE id IN (:id1, :id2, ..., :idN)
"""
product_to_discount_query = sa.LinkQuery(
'db.session',
from_column=Discount.product_id,
to_column=Discount.product_id,
)
"""
SELECT product_id FROM discount
WHERE product_id IN (:id1, :id2, ..., :idN)
"""
Hiku
product_sg = SubGraph(low_level_graph, 'Product')
high_level_graph = Graph([
Node('Product', [
Field('id', String, product_sg),
Field('name', String, product_sg.compile(S.this.name)),
Field('priceText', String, product_sg.compile(
get_price_text(S.this)
)),
Field('hasDiscount', Boolean, product_sg.compile(
is_discount_available(S.this, S.this.discount)
)),
Field('discountedText', String, product_sg.compile(
get_discounted_text(S.this, S.this.discount)
)),
]),
])
@define(Record[{
'price': Float,
'price_currency_id': Integer,
'currency_settings': Any
}])
def get_price_text(product):
product_price_text = format_currency_data(
product_price,
product['price_currency_id'],
)
...
return product_price_text.formatted_number
ORM vs GraphQL
GraphQL -> EdgeDB
GraphQL -> EdgeDB
CREATE DATABASE fwdays;
START TRANSACTION;
CREATE MIGRATION catalog TO {
type Product {
required property name -> str;
property price -> int64;
required link discount -> Discount;
}
type Discount {
required property amount -> int64;
}
};
COMMIT MIGRATION movies;
COMMIT;
INSERT Product {
name := 'random name',
price := 100,
discount := (
INSERT Discount {
amount := 10,
}
)
};
INSERT Product {
name := 'another random name',
price := 200,
discount := (
SELECT Discount
FILTER
.action_id = 1234
LIMIT 1
)
};
GraphQL -> EdgeDB
SELECT Product;
SELECT Product {
name,
price
};
SELECT Product {
name,
price,
discount: {
amount
}
}
FILTER .name ILIKE '%random%';
{
Product {
name
price
}
}
{
Product(filter: {name: {eq: "random"}}) {
name
price
discount {
amount
}
}
}
ORM vs GraphQL
thnx

More Related Content

PPTX
Session #4: Treating Databases as First-Class Citizens in Development
PDF
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
PPTX
Jug trojmiasto 2014.04.24 tricky stuff in java grammar and javac
PDF
Javantura v2 - Making Java web-apps Groovy - Franjo Žilić
PDF
멀티플랫폼 앱 개발과 테스팅
PDF
Javantura v2 - All Together Now - making Groovy and Scala sing together - Din...
PPTX
C# 6.0 Preview
PDF
Unit Testing JavaScript Applications
Session #4: Treating Databases as First-Class Citizens in Development
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Jug trojmiasto 2014.04.24 tricky stuff in java grammar and javac
Javantura v2 - Making Java web-apps Groovy - Franjo Žilić
멀티플랫폼 앱 개발과 테스팅
Javantura v2 - All Together Now - making Groovy and Scala sing together - Din...
C# 6.0 Preview
Unit Testing JavaScript Applications

What's hot (19)

PDF
Streams or Loops? Java 8 Stream API by Niki Petkov - Proxiad Bulgaria
PDF
Ruslan Shevchenko - Property based testing
PDF
TDD and mobile development: some forgotten techniques, illustrated with Android
PPTX
Quickly Testing Qt Desktop Applications
PPTX
Annotation processing tool
PDF
Writing testable code
PDF
Android programming -_pushing_the_limits
PDF
Angular Weekend
PPTX
Дмитрий Демчук. Кроссплатформенный краш-репорт
PDF
Golang dot-testing-lite
PDF
"Ускорение сборки большого проекта на Objective-C + Swift" Иван Бондарь (Avito)
PDF
Extensions vs Services: Digging Deeper - Neil Bartlett
PDF
Agile Developer Immersion Workshop, LASTconf Melbourne, Australia, 19th July ...
PDF
My way to clean android V2
PDF
Architecture for scalable Angular applications (with introduction and extende...
PDF
The Ring programming language version 1.7 book - Part 13 of 196
PDF
Advanced Swift Generics
PPTX
Code generation for alternative languages
PDF
Automated%20testing%20with%20Espresso2.x
Streams or Loops? Java 8 Stream API by Niki Petkov - Proxiad Bulgaria
Ruslan Shevchenko - Property based testing
TDD and mobile development: some forgotten techniques, illustrated with Android
Quickly Testing Qt Desktop Applications
Annotation processing tool
Writing testable code
Android programming -_pushing_the_limits
Angular Weekend
Дмитрий Демчук. Кроссплатформенный краш-репорт
Golang dot-testing-lite
"Ускорение сборки большого проекта на Objective-C + Swift" Иван Бондарь (Avito)
Extensions vs Services: Digging Deeper - Neil Bartlett
Agile Developer Immersion Workshop, LASTconf Melbourne, Australia, 19th July ...
My way to clean android V2
Architecture for scalable Angular applications (with introduction and extende...
The Ring programming language version 1.7 book - Part 13 of 196
Advanced Swift Generics
Code generation for alternative languages
Automated%20testing%20with%20Espresso2.x
Ad

Similar to Oleksandr Tarasenko "ORM vs GraphQL" (20)

PDF
Python BCN Introduction to SQLAlchemy
PDF
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
PDF
pandas.(to/from)_sql is simple but not fast
PDF
PyCon 2010 SQLAlchemy tutorial
PDF
Framework workshop
KEY
Django Pro ORM
PDF
Discover GraphQL with Python, Graphene and Odoo
PPTX
Django - sql alchemy - jquery
PPT
Introduction to Object-Relational Mapping
ODP
Intro To Spring Python
PDF
How to grow GraphQL and remove SQLAlchemy and REST API from a high-load Pytho...
PDF
ORMs in Golang
PDF
Conf orm - explain
PDF
Omnibus database machine
ODP
Introduction to SQL Alchemy - SyPy June 2013
PDF
Drill architecture 20120913
PDF
NoSql Introduction
PPTX
PostgreSQL and JSON with Python - Przemek Lewandowski
PDF
Ariadne: familiar GraphQL in Python
KEY
MongoDB hearts Django? (Django NYC)
Python BCN Introduction to SQLAlchemy
MoSQL: More than SQL, but Less than ORM @ PyCon APAC 2013
pandas.(to/from)_sql is simple but not fast
PyCon 2010 SQLAlchemy tutorial
Framework workshop
Django Pro ORM
Discover GraphQL with Python, Graphene and Odoo
Django - sql alchemy - jquery
Introduction to Object-Relational Mapping
Intro To Spring Python
How to grow GraphQL and remove SQLAlchemy and REST API from a high-load Pytho...
ORMs in Golang
Conf orm - explain
Omnibus database machine
Introduction to SQL Alchemy - SyPy June 2013
Drill architecture 20120913
NoSql Introduction
PostgreSQL and JSON with Python - Przemek Lewandowski
Ariadne: familiar GraphQL in Python
MongoDB hearts Django? (Django NYC)
Ad

More from Fwdays (20)

PDF
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
PDF
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
PPTX
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
PPTX
"Як ми переписали Сільпо на Angular", Євген Русаков
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
PDF
"Validation and Observability of AI Agents", Oleksandr Denisyuk
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
PPTX
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
PPTX
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
PDF
"AI is already here. What will happen to your team (and your role) tomorrow?"...
PPTX
"Is it worth investing in AI in 2025?", Alexander Sharko
PDF
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
PDF
"Scaling in space and time with Temporal", Andriy Lupa.pdf
PDF
"Database isolation: how we deal with hundreds of direct connections to the d...
PDF
"Scaling in space and time with Temporal", Andriy Lupa .pdf
PPTX
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
PPTX
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
PPTX
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
PPTX
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
"Як ми переписали Сільпо на Angular", Євген Русаков
"AI Transformation: Directions and Challenges", Pavlo Shaternik
"Validation and Observability of AI Agents", Oleksandr Denisyuk
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
"AI is already here. What will happen to your team (and your role) tomorrow?"...
"Is it worth investing in AI in 2025?", Alexander Sharko
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Database isolation: how we deal with hundreds of direct connections to the d...
"Scaling in space and time with Temporal", Andriy Lupa .pdf
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...

Recently uploaded (20)

PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
A Presentation on Touch Screen Technology
PDF
Hybrid model detection and classification of lung cancer
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
A Presentation on Artificial Intelligence
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PPTX
OMC Textile Division Presentation 2021.pptx
PDF
Getting Started with Data Integration: FME Form 101
PDF
DP Operators-handbook-extract for the Mautical Institute
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Encapsulation theory and applications.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf
A Presentation on Touch Screen Technology
Hybrid model detection and classification of lung cancer
A comparative study of natural language inference in Swahili using monolingua...
A novel scalable deep ensemble learning framework for big data classification...
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
MIND Revenue Release Quarter 2 2025 Press Release
A Presentation on Artificial Intelligence
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
1 - Historical Antecedents, Social Consideration.pdf
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Univ-Connecticut-ChatGPT-Presentaion.pdf
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
Approach and Philosophy of On baking technology
Accuracy of neural networks in brain wave diagnosis of schizophrenia
OMC Textile Division Presentation 2021.pptx
Getting Started with Data Integration: FME Form 101
DP Operators-handbook-extract for the Mautical Institute
Building Integrated photovoltaic BIPV_UPV.pdf
Encapsulation theory and applications.pdf

Oleksandr Tarasenko "ORM vs GraphQL"

  • 1. ORM vs GraphQL Oleksandr Tarasenko EVO.company / prom.ua
  • 2. Agenda ● Raw SQL in python ● Python ORM libs ● async/await and ORM solutions ● GraphQL implementation 2
  • 4. 4
  • 5. 5
  • 7. Raw SQL in python import psycopg2 class pg_conn: def __enter__(self): self.conn = psycopg2.connect( dbname='fwdays', user='highload' ) return self.conn def __exit__(self, exc_type, exc_val, exc_tb): if hasattr(self, 'conn'): self.conn.close() 7 with pg_conn() as db: cur = db.cursor() query = "insert into product('name') values('toy')" cur.execute(query) db.commit() cur.close() db.close()
  • 8. Raw SQL in python ● psycopg2 ● written in C ● implementation of the DB API 2.0 (PEP 249) ● works like a libpq wrapper 8
  • 9. Raw SQL in python ● psycopg2 ● written in C ● implementation of the DB API 2.0 (PEP 249) ● works like a libpq wrapper 9
  • 10. Raw SQL in python import psycopg2 class pg_conn: def __enter__(self): self.conn = psycopg2.connect( dbname='fwdays', user='highload' ) return self.conn def __exit__(self, exc_type, exc_val, exc_tb): if hasattr(self, 'conn'): self.conn.close() 10 with pg_conn() as db: cur = db.cursor() query = "insert into product('name') values('toy')" cur.execute(query) db.commit() cur.close() db.close()
  • 11. Raw SQL in python insert into products('name') values('toy'); 11
  • 12. Raw SQL in python insert into products('name') values('toy'); select settings from application_settings where company_id in ( 3244414, 3239428, 3246756, 3215974 ); 12
  • 13. Raw SQL in python 13 select csa.company_id, count(csa.id) from company_site_attributes as csa join company as c on c.id = csa.company_id join site_filters as csf on csf.attribute_id = csa.id where portal_attribute_id in (1536, 17536) and c.premium_service_id > 0 and csa.status = 0 and csf.status = 0 group by csa.company_id, csa.id having count(csa.id) > 1;
  • 14. Raw SQL in python 14 select csa.company_id, count(csa.id) from company_site_attributes as csa join company as c on c.id = csa.company_id join site_filters as csf on csf.attribute_id = csa.id where portal_attribute_id in (1536, 17536) and c.premium_service_id > 0 and csa.status = 0 and csf.status = 0 group by csa.company_id, csa.id having count(csa.id) > 1;
  • 15. Raw SQL ● small tables 15
  • 16. Raw SQL ● small tables ● few tables 16
  • 17. Raw SQL ● small tables ● few tables ● no complicated types 17
  • 18. Raw SQL ● small tables ● few tables ● no complicated types ● no need to manage scheme in the app 18
  • 19. Raw SQL ● small tables ● few tables ● no complicated types ● no need to manage scheme in the app ● no migrations 19
  • 20. Raw SQL ● small tables ● few tables ● no complicated types ● no need to manage scheme in the app ● no migrations ● no dynamic queries 20
  • 21. Raw SQL ● small tables ● few tables ● no complicated types ● no need to manage scheme in the app ● no migrations ● no dynamic queries ● no app session managing ● ... 21
  • 23. Python ORM ● SQLAlchemy ● Django ORM ● Peewee ● Pony ORM ● Tortoise ORM ● SQLObject ● GINO * ● ... 23
  • 24. Python ORM + ● Scalability ● Security ● Trust ● Time 24
  • 25. Python ORM - ● Speed ● Scope 25
  • 28. 28
  • 29. 29
  • 30. 30
  • 31. 31
  • 32. 32
  • 38. SQLAlchemy -> asyncio ● psycopg ● aiopg ● asyncpg
  • 42. GraphQL in Python ● Graphene ● Ariadne ● Strawberry ● Hiku
  • 43. Graphene from graphene import ObjectType, String, Schema class Query(ObjectType): name = String(description='Name field') formated_price = String(description='Price field') def resolve_name(self, info): name = get_product_name() ... return name def resolve_price(self, info): price = get_product_price() ... return format_price(price) schema = Schema(query=Query) query = ''' query Products { name price } ''' result = schema.execute(query)
  • 44. Graphene Base = declarative_base() Base.query = db_session.query_property() class ProductModel(Base): __tablename__ = 'product' id = Column(Integer, primary_key=True) name = Column(String) price = Column(Integer) class Product(SQLAlchemyObjectType): class Meta: model = ProductModel interfaces = (relay.Node, ) class Query(ObjectType): node = relay.Node.Field() products = SQLAlchemyConnectionField(Product) schema = Schema(query=Query, types=[Product, ])
  • 45. Graphene query = ''' { products { edges { node { name price } } } } '''
  • 46. Ariadne from ariadne import ObjectType, QueryType, gql, make_executable_schema from ariadne.asgi import GraphQL type_defs = gql(""" type Query { products: [Product!]! } type Product { id: Int name: String price: Int } """) query = QueryType() @query.field("products") def resolve_products(*_): ... return get_products_from_db() product = ObjectType("Product") @product.field("name") def resolve_product_name(product, *_): ... return get_product_name_from_db() schema = make_executable_schema(type_defs, query, product) app = GraphQL(schema, debug=True)
  • 48. Hiku from hiku.graph import Graph, Node, Link, Field, ... from hiku.sources import sqlalchemy as sa from hiku.types import Boolean, Integer, String, TypeRef, ... product_query = sa.FieldsQuery('db.session', Product.table) # product_query = asyncsa.FieldsQuery('db.session_async', Product.table) low_level_graph = Graph([ Node('Product', [ Field('id', Integer, product_query), Field('name', String, product_query), Field('price', None, product_query), ... ]) query = ''' product(ids: [1234, 1235]) { id name price } ''' """ SELECT id, name, price FROM product WHERE id IN (:id1, :id2, ..., :idN) """
  • 49. Hiku low_level_graph = Graph([ Node('Product', [ Field('id', Integer, product_query), ... Link( 'discount', Optional[TypeRef['Discount']], product_to_discount_query, requires='id', ), ]), Node('Discount', [ Field('id', Integer, discount_query), Field('amount', Integer, discount_query), ]) ]) discount_query = sa.FieldsQuery('db.session', Discount.__table__) """ SELECT id, name, price, price_currency_id FROM product WHERE id IN (:id1, :id2, ..., :idN) """ product_to_discount_query = sa.LinkQuery( 'db.session', from_column=Discount.product_id, to_column=Discount.product_id, ) """ SELECT product_id FROM discount WHERE product_id IN (:id1, :id2, ..., :idN) """
  • 50. Hiku product_sg = SubGraph(low_level_graph, 'Product') high_level_graph = Graph([ Node('Product', [ Field('id', String, product_sg), Field('name', String, product_sg.compile(S.this.name)), Field('priceText', String, product_sg.compile( get_price_text(S.this) )), Field('hasDiscount', Boolean, product_sg.compile( is_discount_available(S.this, S.this.discount) )), Field('discountedText', String, product_sg.compile( get_discounted_text(S.this, S.this.discount) )), ]), ]) @define(Record[{ 'price': Float, 'price_currency_id': Integer, 'currency_settings': Any }]) def get_price_text(product): product_price_text = format_currency_data( product_price, product['price_currency_id'], ) ... return product_price_text.formatted_number
  • 53. GraphQL -> EdgeDB CREATE DATABASE fwdays; START TRANSACTION; CREATE MIGRATION catalog TO { type Product { required property name -> str; property price -> int64; required link discount -> Discount; } type Discount { required property amount -> int64; } }; COMMIT MIGRATION movies; COMMIT; INSERT Product { name := 'random name', price := 100, discount := ( INSERT Discount { amount := 10, } ) }; INSERT Product { name := 'another random name', price := 200, discount := ( SELECT Discount FILTER .action_id = 1234 LIMIT 1 ) };
  • 54. GraphQL -> EdgeDB SELECT Product; SELECT Product { name, price }; SELECT Product { name, price, discount: { amount } } FILTER .name ILIKE '%random%'; { Product { name price } } { Product(filter: {name: {eq: "random"}}) { name price discount { amount } } }
  • 56. thnx