Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python sqlalchemy,将ID列表转换为对象列表_Python_Sqlalchemy - Fatal编程技术网

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

Python sqlalchemy,将ID列表转换为对象列表,python,sqlalchemy,Python,Sqlalchemy,我有要检索的ID序列。很简单: session.query(Record).filter(Record.id.in_(seq)).all() 有更好的方法吗?我建议您看看它生成的SQL。您只需打印str(查询)即可查看它 我不知道用标准SQL实现这一点的理想方法。您的代码非常好 中的就像是一堆X=Y与或连接在一起,在当代数据库中速度非常快 但是,如果ID列表很长,则可以通过传递返回ID列表的子查询来提高查询效率。如果使用复合主键,则可以使用元组,如中所示 from sqlalchemy imp

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

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

有更好的方法吗?

我建议您看看它生成的SQL。您只需打印str(查询)即可查看它


我不知道用标准SQL实现这一点的理想方法。

您的代码非常好

中的
就像是一堆
X=Y
连接在一起,在当代数据库中速度非常快


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

如果使用复合主键,则可以使用
元组,如中所示

from sqlalchemy import tuple_
session.query(Record).filter(tuple_(Record.id1, Record.id2).in_(seq)).all()

请注意,这在SQLite上不可用(请参阅)。

还有一种方法;如果可以合理预期相关对象已加载到会话中;您以前在同一事务中访问过它们,现在可以执行以下操作:

map(session.query(Record).get, seq)
在这些对象已经存在的情况下,这将快得多,因为不会有任何查询来检索这些对象;另一方面,如果没有加载的对象数量超过一小部分,则加载速度会慢得多,因为这将导致对每个缺少的实例进行查询,而不是对所有对象进行单个查询


当您在执行上述步骤之前执行
joinedload()
查询时,这可能非常有用,因此您可以确保这些查询已经加载。一般来说,默认情况下,您应该使用问题中的解决方案,并且只有在您看到一遍又一遍地查询相同的对象时,才能探索此解决方案。

原样的代码是完全正确的。然而,有人问我,在对单个ID使用get()的两种方法之间,需要一些对冲系统

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

 all_ids = [<huge list of 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_]
         <work on my_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

你不喜欢它的什么地方?它不起作用吗?看起来应该是这样的。它很有效,我只是想知道是否有更好的方法。你说的“更好”是什么意思?您不喜欢这方面的什么?请注意,如果
seq
足够长,可能会出现“太多SQL变量”异常,因为IN子句已参数化,并且参数太多。谢谢,这正是我要找的!
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