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

时间:2015-12-15 21:26:30

标签: python sqlalchemy

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

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

my_user = User.query().filter(User.ID == 5).first()

my_user = User.query().get(5)

3 个答案:

答案 0 :(得分:8)

这两行是一回事。只有例外情况有所不同实际上,get()是在one()之上实现的。如果您的filter()返回的结果超过了结果会有所不同,但在您的情况下确实无法做到这一点。

顺便说一下,SQL没有GET操作,它只有SELECT(可选LIMIT)。

sqlalchemy/orm/query.py

def get(self, ident):
    ...
    return self._get_impl(ident, loading.load_on_ident)

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

q.one() in turn calls 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()")

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

答案 1 :(得分:5)

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.

此外,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.

答案 2 :(得分:1)

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

(注意:这是第一印象;我没有使用SQLAlchemy,虽然我有多年的编程经验)