当前位置:  开发笔记 > 编程语言 > 正文

sqlalchemy,将ID列表转换为对象列表

如何解决《sqlalchemy,将ID列表转换为对象列表》经验,为你挑选了2个好方法。

我有要检索的ID序列.这很简单:

session.query(Record).filter(Record.id.in_(seq)).all()

有没有更好的方法呢?



1> Adam Dziendz..:

你的代码绝对好.

IN就像一堆X=Y加入,OR在当代数据库中相当快.

但是,如果您的ID列表很长,则可以通过传递返回ID列表的子查询来提高查询效率.



2> zzzeek..:

代码完全没问题.然而,有人要求我在两个做大IN的方法和使用个人ID的get()之间进行一些对冲系统.

如果有人真的试图避免使用SELECT,那么最好的方法就是提前在内存中设置所需的对象.比如,你正在研究一个大的元素表.将工作分解为块,例如,按主键或日期范围排序整套工作,然后将该块的所有内容本地加载到缓存中:

 all_ids = []

 all_ids.sort()
 while all_ids:
     chunk = all_ids[0:1000]

     # bonus exercise!  Throw each chunk into a multiprocessing.pool()!
     all_ids = all_ids[1000:]

     my_cache = dict(
           Session.query(Record.id, Record).filter(
                 Record.id.between(chunk[0], chunk[-1]))
     )

     for id_ in chunk:
         my_obj = my_cache[id_]
         

这是现实世界的用例.

但是为了说明一些SQLAlchemy API,我们可以创建一个函数来为我们没有的记录创建IN,为我们做的那些创建本地get.这是:

from sqlalchemy import inspect


def get_all(session, cls, seq):
    mapper = inspect(cls)
    lookup = set()
    for ident in seq:
        key = mapper.identity_key_from_primary_key((ident, ))
        if key in session.identity_map:
            yield session.identity_map[key]
        else:
            lookup.add(ident)
    if lookup:
        for obj in session.query(cls).filter(cls.id.in_(lookup)):
            yield obj

这是一个演示:

from sqlalchemy import Column, Integer, create_engine, String
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base
import random

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    data = Column(String)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

ids = range(1, 50)

s = Session(e)
s.add_all([A(id=i, data='a%d' % i) for i in ids])
s.commit()
s.close()

already_loaded = s.query(A).filter(A.id.in_(random.sample(ids, 10))).all()

assert len(s.identity_map) == 10

to_load = set(random.sample(ids, 25))
all_ = list(get_all(s, A, to_load))

assert set(x.id for x in all_) == to_load

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有