Как фильтровать с помощью вложенного jsonb с sqlalchemy и postgres - PullRequest
1 голос
/ 09 июля 2019

Я не могу понять, как использовать SQLAlchemy для запроса таблицы, содержащей данные JSONB.

Структура JSON похожа на эту:

example = {
  "product": "Widget",
  "version": 1,
  "release_date": "2019-07-01T00:00:00.000Z",
  "widget": {
    "code": "ABCDEF",
    "name": "my widget",
    "uses": {
        "rain": "yes",
        "snow": "no",
        "heat": "sometimes",
...

Я пытаюсьвыполнить запрос с этой функциональностью:

SELECT
    json  AS acdata
FROM
    aircraft.aircraft
WHERE json -> 'widget' -> 'uses' ->> 'rain' = 'No';

в этой форме:

widget= session.query(Widget).filter_by(rain='No').first()

Я знаю, что дождь = 'Нет' не правильно, но я не могу понять, что должноиди туда!Цель состоит в том, чтобы получить первый виджет, ключ которого widget.uses.rain = 'No'

У меня есть это определение для моего класса Widget

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.dialects.postgresql import JSONB, UUID

class Widget(Base):
    __tablename__ = 'widgets'
    __table_args__ = {'schema' : 'factory'}

    id = Column(UUID(as_uuid=True), primary_key=True)
    json = Column(JSONB, nullable=False)
...

1 Ответ

1 голос
/ 09 июля 2019

Для доступа к вложенному значению jsonb используйте набор ключей (операция индекса пути) и astext для преобразования значения в текст:

widget = session.query(Widget).\
    filter(Widget.json["widget", "uses", "rain"].astext == 'No').\
    first()

В результирующем запросе используется оператор #>>для индекса пути + операция astext.Вы не можете использовать filter_by() для этого вида предиката, так как он используется для простых проверок на равенство атрибутов модельного класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...