代码之家  ›  专栏  ›  技术社区  ›  offby1

在我的mapperExtension.create_实例中,如何按列名提取单个行数据?

  •  1
  • offby1  · 技术社区  · 14 年前

    我有一个返回相当数量行的查询,并且发现

    • 我们最终丢弃了大多数相关的orm实例;并且
    • 建立那些即将被丢弃的实例是相当缓慢的。

    所以我只想建立我需要的实例!

    不幸的是,我不能通过简单地限制查询来实现这一点;我需要对每一行进行相当多的“业务逻辑”处理,然后才能判断是否要抛出它;我不能在sql中实现这一点。

    所以我想我可以使用mapperextension来处理这个问题:我将mapperextension子类化,然后重写create_instance;该方法将检查行数据,如果数据值得构建到实例中,则返回ext_continue,或者……其他的事情(我还没决定做什么)。

    首先,这种方法有意义吗?

    其次,如果它确实有意义的话,我还不知道如何在传递给的参数中找到所需的数据 create_instance . 我怀疑它在里面,但很难找到…我得到的行不是直接对应于我感兴趣的特定类,而是对应于 查询 sqlalchemy生成的,恰好是表a、b和c之间有点复杂的连接。

    问题是,我不知道行中的哪些元素对应于orm类中的字段:我希望能够提取(例如)a.id、b.weight和c.height。

    我假设mapper、selectcontext或class_u参数中的某个位置是表中列之间的某种映射,并偏移到行中。但我还没有找到合适的东西。不过,我已经非常接近了。例如,我发现 selectcontext.statement.columns 包含 生成 柱。。。但不是我感兴趣的那张桌子。例如:

    Column(u'A_id', UUID(), ...
    ...
    Column(u'%(32285328 B)s_weight, MSInt(), ...
    ...
    Column(u'%(32285999 C)s_height', MSInt(), ...
    

    那么:如何将c.height之类的列名映射到 行?

    1 回复  |  直到 14 年前
        1
  •  1
  •   zzzeek    14 年前

    行接受列对象作为索引:

    row[MyClass.some_element.__clause_element__()]
    

    但这只能让您在外部访问类和aliased()构造。很有可能这就是你在这部分问题上所需要的一切(尽管最终这个想法行不通,继续读下去)。

    如果您的语句包含子查询,从使用from_self()或join()到多态目标,create_instance()方法不允许您访问完成该操作所需的转换函数。

    如果您试图获取链接到eagendload()的行,那么这完全不是您应该做的事情。eaginload()是关于优化集合的加载。如果希望查询在两个表之间联接,并且希望对联接的表进行筛选,请使用join()。

    但最重要的是,create_instance()来自sqlalchemy的0.1版本,我怀疑有人会将它用于任何事情,而且它没有能力说“跳过这一行”。它必须返回一些内容,否则映射器将自己创建实例。所以不管你对这一行的理解有多好,这里都没有你想做的事情。

    如果我真的想这样做,那么monkeypatch返回的resultproxy的“fetchall()”方法来过滤行并将其发送到query.instances()可能会更容易。任何结果都可以发送到此方法。尽管如此,如果查询已经对映射的可选择项进行了翻译等操作,那么它还需要原始的querycontext来知道如何翻译。但这也不是我要担心的。

    总的来说,如果速度在整个过程中都是一个非常关键的问题,以至于创建对象有那么大的区别,我会这样做,以便在整个操作中根本不需要映射对象,或者使用缓存,或者从结果集中手动生成所需的对象。我还将确保能够访问正在使用的可选列中的所有目标列,以便可以从结果行中重新获取数据,这意味着我要么不在or m中使用自动子查询/别名生成函数,要么直接使用表达式语言(如果您真的很渴望速度如果你想写大量的优化代码,你应该使用表达式语言。

    所以你要问的真正问题是:

    1. 您是否验证了真正的速度差异是从行创建对象。即不获取行或其列等。
    2. 行中是否有一些不需要的昂贵列?你查过延迟的吗?
    3. 这些业务规则是什么,为什么不能用sql、存储过程等来实现。
    4. 你真的跳过了多少行,以至于不跳过它们太“慢”了
    5. 你有没有研究过让对象已经存在的技术,比如内存缓存、预加载等等。对于许多场景,这是合适的。
    6. 这些都不起作用,你真的想破解一些本地优化代码。那么为什么不直接使用sql表达式语言呢?如果最终您只是处理一个视图层,那么结果行非常友好(它们允许“属性”样式的访问等),或者从中构建一些快速的“生成对象”例程。orm提供了sql表达式语言的一个非常特殊的用例,如果您真的需要比它轻得多的东西,那么最好跳过它。