SQL Alchemy ORM返回单列,如何避免常见的后期处理

Der*_*itz 68 python orm sqlalchemy

我正在使用SQL Alchemy的ORM,当我返回单个列时,我发现我得到的结果如下:

[(result,), (result_2,)] # etc...
Run Code Online (Sandbox Code Playgroud)

有了这样的一套,我发现我必须经常这样做:

results = [r[0] for r in results] # So that I just have a list of result values
Run Code Online (Sandbox Code Playgroud)

这不是"坏",因为我的结果集通常很小,但如果不是这样,可能会增加很多开销.最重要的是我觉得它使源变得混乱,错过这一步是我遇到的一个非常常见的错误.

有没有办法避免这个额外的步骤?

一个相关的旁白:在ORM的这种行为似乎在这种情况下不方便,但在我的结果集是另一种情况,[(ID,值)]它最终是这样的:

[(result_1_id, result_1_val), (result_2_id, result_2_val)]
Run Code Online (Sandbox Code Playgroud)

然后我可以这样做:

results = dict(results) # so I have a map of id to value
Run Code Online (Sandbox Code Playgroud)

这个有一个优点,在返回结果后作为一个有用的步骤.

这真的是一个问题,还是我只是一个挑剔的事情,获得​​结果集后的后期处理对两种情况都有意义?我确信我们可以考虑其他一些常见的后处理操作,以使结果集在应用程序代码中更加可用.是否有全面的高性能和方便的解决方案,或者后处理是不可避免的,仅仅需要不同的应用程序使用?

当我的应用程序实际上可以由SQL炼金术的ORM返回的对象的优势似乎非常有帮助,但在情况下,我不能或不会,没有这么多.这一般只是ORM的常见问题吗?在这样的情况下,我最好不要使用ORM层吗?

我想我应该展示一下我正在谈论的实际orm查询的一个例子:

session.query(OrmObj.column_name).all()
Run Code Online (Sandbox Code Playgroud)

要么

session.query(OrmObj.id_column_name, OrmObj.value_column_name).all()
Run Code Online (Sandbox Code Playgroud)

当然,在真正的查询中通常会有一些过滤器等.

小智 22

Python的zip结合*内联扩展运算符是一个非常方便的解决方案:

>>> results = [('result',), ('result_2',), ('result_3',)]
>>> zip(*results)
[('result', 'result_2', 'result_3')]
Run Code Online (Sandbox Code Playgroud)

然后你只需要[0]索引一次.对于这么短的清单,你的理解力会更快:

>>> timeit('result = zip(*[("result",), ("result_2",), ("result_3",)])', number=10000)
0.010490894317626953
>>> timeit('result = [ result[0] for result in [("result",), ("result_2",), ("result_3",)] ]', number=10000)
0.0028390884399414062
Run Code Online (Sandbox Code Playgroud)

但是对于更长的列表,zip应该更快:

>>> timeit('result = zip(*[(1,)]*100)', number=10000)
0.049577951431274414
>>> timeit('result = [ result[0] for result in [(1,)]*100 ]', number=10000)
0.11178708076477051
Run Code Online (Sandbox Code Playgroud)

因此,您可以自行决定哪种情况更适合您的情况.


Dag*_*ahl 19

减少源中混乱的一种方法是迭代如下:

results = [r for (r, ) in results]
Run Code Online (Sandbox Code Playgroud)

虽然这个解决方案比使用[]操作符长一个字符,但我觉得它在眼睛上更容易.

为了减少杂乱,请删除括号.这使得在阅读代码时更加困难,注意到你实际上正在处理元组,但是:

results = [r for r, in results]
Run Code Online (Sandbox Code Playgroud)


b30*_*000 18

从版本 1.4 开始,SQLAlchemy 提供了一种以值列表形式检索单列结果的方法:

# ORM
>>> session.scalars(select(User.name)).all()
['ed', 'wendy', 'mary', 'fred']
# or
>>> query = session.query(User.name)
>>> session.scalars(query).all()
['ed', 'wendy', 'mary', 'fred']

# Core
>>> with engine.connect() as connection:
...     result = connection.execute(text("select name from users"))
...     result.scalars().all()
... 
['ed', 'wendy', 'mary', 'fred']
Run Code Online (Sandbox Code Playgroud)

请参阅SQLAlchemy 文档

  • @josemfc,如果您使用的是 ORM,您可以执行 `session.scalars(session.query(MyModel.id))` 或 `session.scalars(select(MyModel.id))` 。 (5认同)

Pak*_*man 13

我也在努力解决这个问题,直到我意识到它和其他查询一样:

for result in results:
     print result.column_name
Run Code Online (Sandbox Code Playgroud)