在SQLAlchemy中查找值的最佳实践是什么?

在SQLAlchemy中查找值的最佳实践是什么?,sqlalchemy,flask-sqlalchemy,Sqlalchemy,Flask Sqlalchemy,我正在编写一个非常基本的Flask应用程序,使用Flask SQLAlchemy跟踪库存和分发。我可以用一些指导来说明如何最好地处理公共值的查找表。我的数据库后端将是MySQL和ElasticSearch搜索 如果我有一个通用的映射结构,其中所有进入特定表的数据(例如车辆)都有一个通用的值列表来查找车辆。生成列,那么实现这一点的最佳方法是什么 我的想法有两种: 查找表 我可以在有关系的地方设置类似的设置,并将make存储在车辆make中。然而,如果我期望的品牌列表很低(比如说10个),这似乎是不

我正在编写一个非常基本的Flask应用程序,使用
Flask SQLAlchemy
跟踪库存和分发。我可以用一些指导来说明如何最好地处理公共值的查找表。我的数据库后端将是MySQL和ElasticSearch搜索

如果我有一个通用的映射结构,其中所有进入特定表的数据(例如
车辆
)都有一个通用的值列表来查找
车辆。生成
列,那么实现这一点的最佳方法是什么

我的想法有两种:

查找表

我可以在有关系的地方设置类似的设置,并将make存储在
车辆make
中。然而,如果我期望的品牌列表很低(比如说10个),这似乎是不必要的

class车辆品牌(车型):
id=列(整数,主键=True)
名称=列(字符串(16))
cars=关系('Vehicle',backref='make',lazy='dynamic')
车辆类别(型号):
id=列(整数,主键=True)
名称=列(字符串(32))
存储为字符串

我可以将其作为字符串存储在
车辆
模型上。但将公共值存储为字符串会浪费空间吗

等级车辆(型号):
id=列(整数,主键=True)
名称=列(字符串(32))
make=列(字符串(16))
我最初的想法是创建一个包含这样一个映射的dict,并根据需要在模型中引用它。我只是不清楚在返回车型时如何将其连接起来

制作列表={
1:‘福特’,
2:‘道奇’,
3:“雪佛兰”
}
任何反馈都是欢迎的——如果有文档涵盖了这个特定场景,我很乐意阅读并亲自回答这个问题。我的预期音量将很低(每周40-80条记录),因此不需要太快,我只想遵循最佳实践。

简单的回答是,这取决于具体情况

长期的答案是,这取决于您存储的产品以及所述车辆的品牌,以及您希望添加新车型的频率

如果您需要存储的不仅仅是每个品牌的名称,还需要一些额外的元数据,比如油箱的大小、货物空间,甚至是排序键,那么可以使用额外的表。这样一个小表的开销是最小的,如果您使用makeid而不是makename与前端通信,这一点没有问题。只需记住在
车辆中添加索引。使用_id
以提高查找效率

class车辆品牌(车型):
id=列(整数,主键=True)
名称=列(字符串(16))
cars=关系('Vehicle',back_populates=“make”,lazy='dynamic')
车辆类别(型号):
id=列(整数,主键=True)
名称=列(字符串(32))
make_id=列(整数,ForeignKey('vehicle_make.id'),null=False)
make=关系(“VehicleType”,innerjoin=True)
Vehicle.query.get(1).make.name#=='Ford',车辆1的品牌
Vehicle.query.filter(Vehicle.make_id==2).all()#所有make id为2的车辆
Vehicle.query.join(VehicleMake)\
.filter(VehicleMake.name==“Ford”).all()#所有品牌名称为“Ford”的车辆
如果不需要存储任何元数据,那么就不需要单独的表了。但是,字符串的一般问题是存在拼写错误和大小写字母破坏数据一致性的高风险。如果您不需要添加新的make,只使用它会更好,甚至在SQLAlchemy中也有特定于MySQL的

导入枚举
类别车辆制造商(枚举):
福特=1
道奇=2
雪佛兰=3
车辆类别(型号):
id=列(整数,主键=True)
名称=列(字符串(32))
make=列(枚举(车辆make),可空=False)
Vehicle.query.get(1).make.name#=='FORD',车辆1的品牌
Vehicle.query.filter(Vehicle.make==VehicleMake(2)).all()#所有品牌id为2的车辆
Vehicle.query.filter(Vehicle.make==VehicleMake.FORD).all()#品牌名为“FORD”的所有车辆
ENUM的主要缺点是,它们可能很难用新值进行扩展,尽管至少对于Postgres来说,方言特定的版本在这方面比一般的SQLAlchemy版本要好得多,但是请看
SQLAlchemy.dialogs.mysql.ENUM
。尽管如果您想扩展现有的枚举,您始终可以在Flask Migrate/Alembic迁移中执行

最后是使用字符串的好处。主要是,您可以始终以编程方式强制实现数据一致性。但是,这是以您必须以编程方式强制实现数据一致性为代价的。如果外部用户,甚至同事可以更改或插入车辆品牌,这将给您带来麻烦,除非您对进入数据库的内容非常严格。例如,为了便于分组,最好将所有值都大写,因为这样可以有效地减少可能出现的错误。您可以在编写过程中执行此操作,也可以在
sqlalchemy.func.upper(Vehicle.make)
上添加索引,并使用它始终查询大写值

等级车辆(型号):
id=列(整数,主键=True)
名称=列(字符串(32))
_make=列('make',字符串(16))
@杂化性
def品牌(自我):
返回自我。_make.upper()
@表达
def品牌(cls):
返回函数上限(cls.\u make)
Vehicle.query.get(1.make.upper()#==“FORD”,车辆1的品牌
Vehicle.query.filter(Vehicle.make==“FORD”).all()#所有品牌名称为“FORD”的车辆
在您做出选择之前,还要考虑一下您希望如何向您的用户展示这一点。如果他们应该能够自己添加新选项,请使用字符串或单独的表。如果你想展示一个dr