0

在我的架构中,硬件项目可能记录了零个或多个 Mod。我正在尝试根据与 mod 列表的完全匹配来过滤查询。例如,我可能想过滤具有 mods [2,3,5] 的硬件,而没有其他的。

目前,我正在分组和计数以检查 mod 的数量是否正确,然后在 for 循环中添加一个过滤器以匹配确切的 mod 编号:

...
query = query.join(Hardware).join(Mod)
query = query.group_by(Tag.tag_id).having(len(v['m']) == func.count(Mod.mod_number))
for m in v['m']:
    query = query.filter(Hardware.mods.any(mod_number=m))
...

有没有更好的方法来使用 SQLAlchemy 来表达这一点?特别是,文档建议不要使用func.count(),因为它在某些极端情况下会失败..

我的架构如下所示:

Base = declarative_base()


class Tag(Base):
    __tablename__ = 'tag'
    tag_id = Column(Integer, primary_key=True)
    order_code = Column(String, nullable=False)
    version = Column(String, nullable=False)
    status = Column(String, nullable=False)
    comments = Column(String)
    software = relationship(
        "Software",
        backref="tag",
        collection_class=attribute_mapped_collection('artefact'),
    )
    hardware = relationship(
        "Hardware",
        backref="tag",
        collection_class=attribute_mapped_collection('artefact'),
    )
    __table_args__ = (
        UniqueConstraint('order_code', 'version'),
    )

    def as_dict(self):
        d = as_dict_columns(self)
        d['software'] = {s: as_dict_columns(self.software[s]) for s in self.software}
        d['hardware'] = {h: self.hardware[h].as_dict() for h in self.hardware}
        return d


class Software(Base):
    __tablename__ = 'software'
    software_id = Column(Integer, primary_key=True)
    tag_id = Column(String, ForeignKey('tag.tag_id'))
    artefact = Column(String, nullable=False)
    version = Column(String, nullable=False)
    __table_args__ = (
        UniqueConstraint('tag_id', 'artefact'),
    )

    def __str__(self):
        """ This is to deal with Jinja2/SQLAlchemy wackiness """
        return self.version


class Hardware(Base):
    __tablename__ = 'hardware'
    hardware_id = Column(Integer, primary_key=True)
    tag_id = Column(String, ForeignKey('tag.tag_id'))
    product_id = Column(String, nullable=True)
    artefact = Column(String, nullable=False)
    version = Column(String, nullable=False)
    mods = relationship("Mod", backref="hardware")
    __table_args__ = (
        UniqueConstraint('tag_id', 'product_id'),
    )

    def as_dict(self):
        d = as_dict_columns(self)
        d['mods'] = self.__list_mods__()
        return d

class Mod(Base):
    __tablename__ = 'mod'
    hardware_id = Column(String, ForeignKey('hardware.hardware_id'), primary_key=True)
    mod_number = Column('mod_number', Integer, primary_key=True, nullable=False)
    __table_args__ = (
        UniqueConstraint('hardware_id', 'mod_number'),
    )
4

0 回答 0