sqlite 如何在sqlalchemy中排序简单的SemVer版本字符串

icomxhvb  于 2023-04-06  发布在  SQLite
关注(0)|答案(1)|浏览(115)

我在数据库和SQLAlchemy方面是个新手。
我有一个模型

class MySoftware(Base):

    __tablename__ = "my_software"
    version: Mapped[str] = mapped_column(primary_key=True)

其中version看起来像简单的semver(例如0.0.10.4.21.2.0)。
我需要的是使用这个字符串执行简单的排序,类似于

db.scalars(select(MySoftware).order_by(asc("version"))).all()

我读了很多关于混合财产和这么多奇怪的概念对我来说,我找不到一个方法。
有人能告诉我如何做到这一点吗?
这里有一个最小的代码来测试它。

from pprint import pprint

from sqlalchemy import asc, create_engine, desc, select
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column

class Base(DeclarativeBase):
    pass

class MySoftware(Base):

    __tablename__ = "my_software"
    version: Mapped[str] = mapped_column(primary_key=True)

    def __repr__(self):
        return f"MySoftware(version={self.version})"

# Create the engine and the session
engine = create_engine("sqlite://")
Base.metadata.create_all(bind=engine)
db = Session(engine)

version_list = ["0.10.1", "0.2.0", "3.0.1", "2.0.1"]
expected_version_list = ["0.2.1", "0.10.1", "2.0.1", "3.0.1"]

# Write contents
with db.begin():
    for v in version_list:
        db.add(MySoftware(version=v))

# Print the contents with version sorting
with engine.begin():

    s = select(MySoftware).order_by(asc("version"))

    pprint(db.scalars(s).all())

# Close the DB
db.close()

这个返回

[MySoftware(version=0.10.1),
 MySoftware(version=0.2.0),
 MySoftware(version=2.0.1),
 MySoftware(version=3.0.1)]
c6ubokkw

c6ubokkw1#

使用Python的内置排序可能会更有效,比如:

sorted_versions = sorted(unsorted_versions, key=lambda v: semver_key(v.version))

要使用SQLite和SQLAlchemy实现类似的结果,需要修改数据库中的表结构,并更新现有数据,使版本字符串的每个部分都有单独的列。

class MySoftware(Base):
    __tablename__ = "my_software"
    id = Column(Integer, primary_key=True)
    major = Column(Integer)
    minor = Column(Integer)
    patch = Column(Integer)

然后,可以使用ORDERBY子句对这些列直接在SQL查询中对数据进行排序。

sorted_versions = db.query(MySoftware).order_by(MySoftware.major, MySoftware.minor, MySoftware.patch).all()

相关问题