Понимание объединения в SqlAlchemy ORM - PullRequest
0 голосов
/ 30 сентября 2019

У меня на самом деле есть рабочие коды, но мне интересно, можно ли это сделать больше с помощью Sqlalchmey ORM.

У меня есть эти 3 таблицы:

class NodesModel(db.Model):
    __tablename__ = 'nodes'

    id = db.Column(db.BigInteger, primary_key=True)
    project_id = db.Column(db.BigInteger, db.ForeignKey('projects.id'))
    name = db.Column(db.String)

    posts_nodes = relationship("PostsNodesModel", backref="nodes")
class PostsModel(db.Model):
    __tablename__ = 'posts'

    id = db.Column(db.BigInteger, server_default=db.FetchedValue(), primary_key=True)
    project_id = db.Column(db.BigInteger, db.ForeignKey('projects.id'))

    posts_nodes = relationship("PostsNodesModel", backref="posts")
class PostsNodesModel(db.Model):
    __tablename__ = 'posts_nodes'

    post_id = db.Column(db.BigInteger, db.ForeignKey('posts.id'), primary_key=True)
    node_id = db.Column(db.BigInteger, db.ForeignKey('nodes.id'), primary_key=True)

Итак, у меня есть этот запрос, который будет искать имя и получать сообщения, связанные с именем:

return (db.session.query(PostsModel.data_date, NodesModel.topic)
        .join(PostsNodesModel, PostsNodesModel.node_id == NodesModel.id)
        .join(PostsModel, PostsModel.id == PostsNodesModel.post_id)
        .filter(NodesModel.project_uuid == project_uuid)
        .all())

Это работает, но я читаю этот вопрос stackoverflow В SQLAlchemy, в чем разницамежду «фильтром» и «объединением и фильтрацией» синтаксиса?

и заметил, что человек использует метод

.join(Author, Publisher, Retailer)

И этот человек сказал, что отношения заботятся оссылки.

Я пытался сделать это для своего утверждения:

return (db.session.query(NodesModel)
        .with_entities(PostsModel.data_date, NodesModel.topic)
        .join(PostsNodesModel, PostsModel)
        .filter(NodesModel.project_uuid == project_uuid)
        .all())

Но, конечно, это не сработало.

Так что, узнав больше оSqlalchemy, может ли кто-нибудь заставить работать вышеперечисленное и объяснить или указать мне объяснение того, как это можно сделать?

В Sqlalchemy "Конфигурирование присоединения отношений", которая заявляет, чтообычно создают соединение между двумя таблицамиs путем изучения отношения внешнего ключа между двумя таблицами, чтобы определить, какие столбцы следует сравнивать. "Так что на самом деле мое заявление выше должно работать.

Я пытался прочитать документацию по нему, но я все еще не приблизился к пониманию того, как это работает и как заставить его работать.

Другое дело, что нет ни родителя, ни ребенка, поскольку мои запросы выполняются в обоих направлениях, я иногда запрашиваю пост, чтобы получить имена, связанные с этим постом.

Спасибо. Desmond

Ответы [ 2 ]

0 голосов
/ 02 октября 2019

После помощи от Benvc, я искал и ломал голову над этим, и я нашел ответ.

Мои переписанные модели:

class PostsModel(db.Model):
    __tablename__ = 'posts'

    id = db.Column(db.BigInteger, server_default=db.FetchedValue(), primary_key=True)
    project_id = db.Column(db.BigInteger, db.ForeignKey('projects.id'))

    post = relationship("PostsModel", back_populates="nodes")
    node = relationship("NodesModel", back_populates="posts")
class PostsModel(db.Model):
    __tablename__ = 'posts'

    id = db.Column(db.BigInteger, server_default=db.FetchedValue(), primary_key=True)
    project_id = db.Column(db.BigInteger, db.ForeignKey('projects.id'))

    nodes = relationship("PostsNodesModel", back_populates="post")
class PostsNodesModel(db.Model):
    __tablename__ = 'posts_nodes'

    post_id = db.Column(db.BigInteger, db.ForeignKey('posts.id'), primary_key=True)
    node_id = db.Column(db.BigInteger, db.ForeignKey('nodes.id'), primary_key=True)

    posts = relationship("PostsNodesModel", back_populates="node")

Запрос:

return (db.session.query(PostsModel.data_date, NodesModel.topic)
        .join('nodes', 'node')
        .filter(NodesModel.project_uuid == project_uuid)
        .all())

Узлы и узел (в операторе соединения) используют переменную узлов в PostsModel, а узел - переменную в PostsNodesModel.

Интересно, что вам нужнопоставьте узлы на первое место. Если вы измените расположение (т. Е. Соединение ('узел', 'узлы')), Sqlalchemy заявляет, что в PostsModel нет свойства узла. Этот запрос читает из PostsModel в NodesModel, как указано в запросе. Следующее также работает:

return (db.session.query(NodesModel.topic, PostsModel.data_date)
        .join('posts', 'post')
        .filter(NodesModel.project_uuid == project_uuid))

Это создает оператор соединения из NodesModel в PostsModel, и механизм соединения отражает это.

0 голосов
/ 30 сентября 2019

Вы можете попробовать:


query = NodesModel.join(
    PostsNodeModel, PostsNodesModel.node_id == NodesModel.id
).join(
    PostsModel, PostsModel.id == PostsNodesModel.post_id
).filter(
    NodesModel.project_uuid == project_uuid
).with_entities(
 .filter(NodesModel.project_uuid == project_uuid)
)

return query

А из вызывающей функции вы можете просто позвонить .all()

def calling_function():
   query = get_query()
   query.all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...