何时使用SQLAlchemy .get()vs .filter(Foo.ID == primary_key_id).first()

Bob*_*sta 9 python sqlalchemy

只是好奇我什么时候想要使用一个与另一个.他们有什么不同?

我们设置了系统,以便我们可以这样做:

my_user = User.query().filter(User.ID == 5).first()
Run Code Online (Sandbox Code Playgroud)

要么

my_user = User.query().get(5)
Run Code Online (Sandbox Code Playgroud)

And*_*ini 9

这两行是一回事.只有例外情况有所不同 实际上,get()是在上面实现的one().如果您filter()返回的结果超过了结果会有所不同,但在您的情况下确实不可能.

顺便说一句,SQL没有GET操作,它只有SELECT(带有可选的LIMIT).


sqlalchemy/orm/query.py :

def get(self, ident):
    ...
    return self._get_impl(ident, loading.load_on_ident)
Run Code Online (Sandbox Code Playgroud)

sqlalchemy/orm/loading.py:

def load_on_ident(query, key,
                  refresh_state=None, lockmode=None,
                  only_load_props=None):
    ...
    try:
        return q.one()
    except orm_exc.NoResultFound:
        return None
Run Code Online (Sandbox Code Playgroud)

q.one()反过来打电话q.one_or_none().

现在比较first()one_or_none():

def first(self):
    ...
    ret = list(self[0:1])
    if len(ret) > 0:
        return ret[0]
    else:
        return None


def one_or_none(self):
    ...
    ret = list(self)

    l = len(ret)
    if l == 1:
        return ret[0]
    elif l == 0:
        return None
    else:
        raise orm_exc.MultipleResultsFound(
            "Multiple rows were found for one_or_none()")
Run Code Online (Sandbox Code Playgroud)

因此,first()使用LIMIT one_or_none()执行SELECT ,执行无限制的SELECT.但是,正如我们已经说过的,无论是否有LIMIT,查询的结果都不会改变,因此两者是等价的.


osm*_*man 6

Andrea Corbellini的答案的一个重要补充: get如果SQLAlchemy会话中已存在对象,则可以通过从内存中检索对象来提高性能.

sqlalchemy/orm/query.py :

    :meth:`~.Query.get` is special in that it provides direct
    access to the identity map of the owning :class:`.Session`.
    If the given primary key identifier is present
    in the local identity map, the object is returned
    directly from this collection and no SQL is emitted,
    unless the object has been marked fully expired.
    If not present,
    a SELECT is performed in order to locate the object.
Run Code Online (Sandbox Code Playgroud)

此外,如果对象已在会话中过期,get将执行数据库I/O(即SELECT语句)刷新对象:

sqlalchemy/orm/query.py :

    :meth:`~.Query.get` also will perform a check if
    the object is present in the identity map and
    marked as expired - a SELECT
    is emitted to refresh the object as well as to
    ensure that the row is still present.
    If not, :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised.
Run Code Online (Sandbox Code Playgroud)


dsh*_*dsh 1

第一个 ( .filter()) 更通用:您可以为任何列集构造任何条件。后者是按主键查找的常见情况的快捷方式。

(注:这是第一印象;我没有使用过 SQLAlchemy,尽管我确实有多年的编程经验)