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

在Pony ORM中以增量方式构建查询

  •  2
  • fluffy  · 技术社区  · 6 年前

    def Entry(BaseModel):
        # peewee fields go here
    
    def where_entry_category(category, recurse=False):
        """ Generate a where clause for a particular category """
    
        if category or not recurse:
            cat_where = (Entry.category == str(category))
    
            if recurse:
                # We're recursing and aren't in /, so add the prefix clause
                cat_where = cat_where | (
                    Entry.category.startswith(str(category) + '/'))
        else:
            cat_where = True
    
        return cat_where
    
    query = Entry.select().where(where_entry_category("test"))
    

    其工作方式是peewee模型类型上的各种操作符重载只返回一个查询组件树,这些子树可以由进一步的操作符重载组成。有多个查询组件与 & | 操作员,例如。 model.Entry.select().where(some_test() & some_other_test()) . 这是非常有用的,因为我的许多过滤查询都是以模块化的方式组成的,并且大多数底层查询部分经常被重用,而且很多都是非平凡的(例如上面的示例)。

    AST generator parser 和原始SQL。由于原始SQL表单不能让我直接传递必要的查询部分,因此如果可能的话,我更愿意使用一些更高级的查询构建功能。

    class Entry(db.Entity):
        ...
        def in_category(self, category, recurse=False):
            # return a test on the parameters
    
    orm.select(entry for entry in model.Entry if entry.in_category('foo', True)) 
    

    我明白了 NotImplementedError ,毫不奇怪。

    是否有一种机制用于从现有部分构建查询表达式,并将其传递到SQL查询生成器中(可能是通过自己构建AST并将其传递到Pony的相关部分,或者通过一种机制传递一个查询以供另一个子查询过滤。)

    1 回复  |  直到 6 年前
        1
  •  3
  •   Alexander Kozlovsky    6 年前

    在PonyORM中,有两种方法可以逐步组合查询。第一个是 filter 查询方法:

    def where_entry_category(query, category, recourse)
        if category:
            category = str(category)
            if recurse:
                query = query.filter(lambda x: x.category == category or
                                     x.category.startswith(category + '/')
            else:
                query = query.filter(lambda x: x.category == category)
        return query
    
    query = Entry.select()
    query = where_entry_category(query, "test")
    

    从0.7.6版开始,还可以使用以前的查询作为新查询的源:

    def where_entry_category(query, category, recourse)
        if category:
            category = str(category)
            if recurse:
                query = select(x for x in query
                               if x.category == category or
                                  x.category.startswith(category + '/'))
            else:
                query = select(x for x in query if x.category == category)
        return query
    

    or 条款逐渐在将来发布。