【问题标题】:filtering on a range of values in a db column with sqlalchemy orm使用 sqlalchemy orm 过滤 db 列中的一系列值
【发布时间】:2015-02-10 10:59:15
【问题描述】:

我有一个 postgresql 数据库,在一个特定的表中,有很多行。此表中的一列称为数据,是一个浮点数组 REAL[],并填充有约 4500 个元素的数组。我想通过 SQLAlchemy 和 ORM 的一些查询来访问这个表。

如何选择表中该列的子集满足某些条件(例如包含一系列值)的所有行?就像我想选择数据包含值 >= 10 或 >=10 和

我可以通过像这样的直接会话查询来做到这一点

rows = session.query(Table).filter(Table.data.(some conditional)).all()

我的条件类似于“VALUES >= 10 and VALUES

当我定义我的 SQLAlchemy 表类时,我是否需要定义一些特殊的方法或设置。例如,我将表设置为

class Table(Base):
    __tablename__ = 'table'
    __table_args__ = {'autoload' : True, 'schema' : 'testdb', 'extend_existing':True}

    data = deferred(Column(ARRAY(Float)))

    def __repr__(self):
        return '<Table (pk={0})>'.format(self.pk)       

理想情况下,我想设置它,这样我就可以在 session.query 调用中进行简单的过滤。这可能吗?我对 ORM 不是很熟悉,也许是这样?

我查看了 ARRAY Comparator sqlalchemy 文档,但这些文档似乎只适用于精确值。我的数据精确到 6 sigfigs,我不知道提前的确切值。

最好的方法是什么?谢谢。

编辑:

根据下面的评论,这是我在尝试选择具有数据(来自 1 列)>= 1.0 的所有行(共 1000 行)时使用的代码。应该有 537 行。

rows =  session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operators.le)).all()

这给出了正确的子集编号。 len(rows) = 537。但是,我不明白这个运算符的逻辑,在哪里选择数据 >=1.0 ,我使用 le 运算符?此外,按照同样的思路,应该有 234 行的数据介于 >=1.0 和

rows = session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operators.le)).filter(datadb.Table.data.any(1.2,operator=operators.ge)).all()

* 编辑 2 *

这是我的数据库表的示例,其中包含几行。 pk是整数,data是real[]。

db datadb
schema Table 
pk      data
0       [0.0,0.0,0.5,0.3,1.3,1.9,0.3,0.0,0.0]
1       [0.1,0.0,1.0,0.7,1.1,1.5,1.2,0.3,1.4]
2       [0.0,0.6,0.4,0.3,1.6,1.7,0.4,1.3,0.0]
3       [0.0,0.1,0.2,0.4,1.0,1.1,1.2,0.9,0.0]
4       [0.0,0.0,0.5,0.3,0.2,0.1,0.7,0.3,0.1]

我有 5 行,其中 4 行的数据的值 >= 1.0,而只有 2 行的值在 >= 1.0 和

rows = session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operators.le)).all()

这应该返回 4 行,在 pk=0,1,2,3。这个查询符合我的预期。第二种情况

rows = session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operators.le)).filter(datadb.Table.data.any(1.2,operator=operators.ge)).all()

并且应该返回 pk=1,3 处的 2 行。但是,此查询仅返回第一个查询的 4 行。对于第二个查询,我也试过了

rows = session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operators.le),datadb.Table.data.any(1.2,operator=operators.ge)).all()

这也不起作用。

【问题讨论】:

    标签: postgresql orm sqlalchemy subset


    【解决方案1】:

    请阅读ARRAY.Comparator 上的文档,据此您应该能够执行以下操作:

    rows = (session.query(Table)
            .filter(Table.data.any(10, operator=operators.le))
            .filter(Table.data.any(20, operator=operators.ge)
    ).all()
    

    编辑

    # combined filter does not work,
    # but applying one or the other is still useful as it reduces the result set
    q = (session.query(MyTable)
         .filter(MyTable.data.any(1.0, operator=operators.le))
         # .filter(MyTable.data.any(1.2, operator=operators.ge))
         )
    
    # filter in memory
    items = [_row for _row in q.all()
             if any(1.0 <= item <= 1.2 for item in _row.data)]
    
    for item in items:
        print(item)
    

    【讨论】:

    • 所以我在一个有 1000 行的表上尝试了这个,其中 537 行的数据在数组中 >= 1.0。我做了 rows=session.query(datadb.Table).filter(datadb.Table.data.any(1.0,operator=operator.ge)).all(),它返回了相同的 1000 行。
    • 有数据是指有至少一项>= 1.0所有项>= 1.0?您还可以发布执行的SQL 语句吗?
    • 请查看更新后的代码,错字在哪里,data &gt;= 1 应该使用operators.le
    • 回答您的问题,“有数据”是指数据数组至少应包含 1 个元素 >=1.0。我正在编辑我的文本以提供我正在使用的示例代码。我不太明白选择 data >= 1.0 与 le 运算符一起使用的逻辑?当我尝试选择数据 >=1.0 和
    • 再次,请查看更新后的代码:我在现实生活中从未使用过,但看起来操作数颠倒了:(10, le) 表示 value &gt;= 10 将是 TRUE
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多