返回包含所有外键的行

rvpgvaaj  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(301)

我正在使用sqlalchemy,我有一个位置模型和一个过程模型。地方和程序之间是一种多对多的关系,每个地方都有多个程序,一个程序可以由多个地方来完成。
目前,我有一个简单的查询,以便我可以搜索所有的地方,有一个单一的过程。

for place in session.query(Place).filter(Place.procedures.any(Procedure.name == searchProcedure)):

这是正确的,我的查询当前将返回所有具有所需搜索过程的位置。
我想改变它,使我有多个搜索过程,我只返回任何地方,有所有查询的搜索过程。
我有一个工作的解决方案,使用for循环来运行多个过滤器

placeResults = session.query(Place)
    for searchProcedure in proceduresQuery:
        placeResults = placeResults.filter(Place.procedures.any(Procedure.name == searchProcedure))

    for place in placeResults:
        #do desired work with found places here

使用sqlalchemy(或一般的sql)有更好的方法来实现这一点吗?我相信可能有一个更短/更快的解决方案涉及连接,但我不确定。
谢谢!

uujelgoq

uujelgoq1#

至少,如果程序数量相对较少,您可以 and_ 在您的 .filter :

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base

engine = sa.create_engine("sqlite:///:memory:", echo=True)

Base = declarative_base()

# association table

place_procedure = sa.Table(
    "place_procedure",
    Base.metadata,
    sa.Column("place_id", sa.ForeignKey("place.id"), primary_key=True),
    sa.Column("procedure_id", sa.ForeignKey("procedure.id"), primary_key=True),
)

class Place(Base):
    __tablename__ = "place"

    id = sa.Column("id", sa.Integer, primary_key=True, autoincrement=False)
    procedures = sa.orm.relationship(
        "Procedure", secondary=place_procedure, back_populates="places"
    )

    def __init__(self, id, procedures):
        self.id = id
        self.procedures = procedures

    def __repr__(self):
        return f"<Place(id={self.id})>"

class Procedure(Base):
    __tablename__ = "procedure"

    id = sa.Column("id", sa.String(50), primary_key=True)
    places = sa.orm.relationship(
        "Place", secondary=place_procedure, back_populates="procedures"
    )

    def __init__(self, id):
        self.id = id

    def __repr__(self):
        return f"<Procedure(id='{self.id}')>"

Base.metadata.create_all(engine)

Session = sa.orm.sessionmaker(bind=engine)
session = Session()

# test data

proc1 = Procedure("procedure1")
proc2 = Procedure("procedure2")
proc4 = Procedure("procedure4")
place0 = Place(0, [])
place1 = Place(1, [proc1])
place2 = Place(2, [proc2])
place3 = Place(3, [proc2, proc1])
place4 = Place(4, [proc4])
place5 = Place(5, [proc4, proc1])
place6 = Place(6, [proc4, proc2])
place7 = Place(7, [proc4, proc2, proc1])
session.add_all(
    [
        proc1,
        proc2,
        proc4,
        place1,
        place2,
        place3,
        place4,
        place5,
        place6,
        place7,
    ]
)
session.commit

# test code

places_with_procedure1_and_procedure2 = (
    session.query(Place)
    .filter(
        sa.and_(
            Place.procedures.contains(proc1), Place.procedures.contains(proc2)
        )
    )
    .all()
)

print(places_with_procedure1_and_procedure2)
"""console output:
[<Place(id=3)>, <Place(id=7)>]
"""

相关问题