私のスキーマでは、ハードウェア アイテムには 0 個以上の Mod が記録されている場合があります。mod のリストとの完全一致に基づいてクエリをフィルタリングしようとしています。たとえば、モッド [2,3,5] があり、それ以外がないハードウェアをフィルタリングしたい場合があります。
現時点では、mod の数が正しいことを確認するためにグループ化とカウントを行ってから、正確な mod 数と一致するように for ループにフィルターを追加しています。
...
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'),
)