Поле JSONB
Поле JSONB представляет тип данных
для хранения JSON-документов в бинарном виде.
Этот тип доступен только в PostgreSQL
и является более эффективной альтернативой
обычному типу JSON. В отличие от
последнего, JSONB хранит данные
в разобранном бинарном формате, что ускоряет
поиск и индексацию, но замедляет вставку.
При создании поля можно передать параметры
none_as_null и astext_type.
Синтаксис
JSONB(none_as_null=False, astext_type=None)
Пример
Давайте создадим модель с полем JSONB
и запишем в него словарь:
from sqlalchemy import create_engine, JSONB
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
data: Mapped[dict] = mapped_column(JSONB)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(title='article', data={'status': 'published', 'num': 1})
session.add(article)
session.commit()
res = session.query(Article).first()
print(res.data)
Результат выполнения кода:
{'status': 'published', 'num': 1}
Пример
Давайте обратимся к отдельному ключу
JSON-документа через оператор []:
from sqlalchemy import create_engine, JSONB
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
data: Mapped[dict] = mapped_column(JSONB)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Article(title='article', data={'status': 'draft', 'num': 5}))
session.commit()
res = session.query(Article.data['status']).first()
print(res)
Результат выполнения кода:
('draft',)
Пример
Давайте отфильтруем записи по значению вложенного ключа JSON-документа:
from sqlalchemy import create_engine, JSONB
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
data: Mapped[dict] = mapped_column(JSONB)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add_all([
Article(title='article 1', data={'status': 'published'}),
Article(title='article 2', data={'status': 'draft'}),
])
session.commit()
res = session.query(Article).filter(Article.data['status'].as_string() == 'draft').all()
for article in res:
print(article.title)
Результат выполнения кода:
"article 2"