tornado peewee orm查询中的 fn函数 和 prefetch()的使用介绍

让我们列出所有的人以及他们拥有多少宠物:

for person in Person.select():

    print(person.name, person.pets.count(), "pets")

# prints:

# Bob 2 pets

# Grandma L. 0 pets

# Herb 1 pets

再一次,我们遇到了N + 1查询行为的经典示例。在这种情况下,我们Person将对原始查询返回的每个查询执行附加查询 SELECT!我们可以通过执行JOIN并使用SQL函数汇总结果来避免这种情况。

query = (Person

         .select(Person, fn.COUNT(Pet.id).alias("pet_count"))

         .join(Pet, JOIN.LEFT_OUTER)  # include people without pets.

         .group_by(Person)

         .order_by(Person.name))

for person in query:

    # "pet_count" becomes an attribute on the returned model instances.

    print(person.name, person.pet_count, "pets")

# prints:

# Bob 2 pets

# Grandma L. 0 pets

# Herb 1 pets

最后一个查询。这将使用SQL函数查找名称以大写或小写G开头的所有人员:

expression = fn.Lower(fn.Substr(Person.name, 1, 1)) == "g"

for person in Person.select().where(expression):

    print(person.name)

# prints:

# Grandma L.

注意

Peewee提供了一个神奇的助手fn(),可以用来调用任何SQL函数。在上面的示例中,fn.COUNT(Pet.id).alias("pet_count") 将被翻译成。COUNT(pet.id) AS pet_count

现在,让我们列出所有的人和他们所有宠物的名字。您可能已经猜到了,如果我们不小心的话,这很容易变成另一种N + 1的情况。

在深入研究代码之前,请考虑该示例与之前的示例有何不同,在前面的示例中我们列出了所有宠物及其所有者的名字。一只宠物只能有一个所有者,因此当我们执行从Pet到的联接时Person,总是会有一个匹配项。当我们从Person到加入时,情况会有所不同,Pet因为一个人可能有零只宠物,或者他们可能有几只宠物。因为我们使用的是关系数据库,所以如果要进行从Person到的联接,Pet那么每个拥有多个宠物的人都会被重复,每个宠物一次。

附:

substr() 函数

定义和用法

substr() 函数返回字符串的一部分。

注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

语法

substr(string,start,length)

• string

• 必需。

• 规定要返回其中一部分的字符串。

• start

• 必需。

• 规定在字符串的何处开始。

• 正数 - 在字符串的指定位置开始

• 负数 - 在从字符串结尾的指定位置开始

• 0 - 在字符串中的第一个字符处开始

• length

•  可选

• 。规定要返回的字符串长度。

• 默认是直到字符串的结尾。

• 正数 - 从 start 参数所在的位置返回

• 负数 - 从字符串末端返回

• 返回值

• 返回字符串的提取部分,如果失败则返回 FALSE,或者返回一个空字符串

它看起来像这样:

query = (Person

         .select(Person, Pet)

         .join(Pet, JOIN.LEFT_OUTER)

         .order_by(Person.name, Pet.name))

for person in query:

    # We need to check if they have a pet instance attached, since not all

    # people have pets.

    if hasattr(person, "pet"):

        print(person.name, person.pet.name)

    else:

        print(person.name, "no pets")

# prints:

# Bob Fido

# Bob Kitty

# Grandma L. no pets

# Herb Mittens Jr

通常,这种类型的复制是不可取的。为了适应列出某人并附加该人宠物清单的更常见(直观)的工作流程,我们可以使用一种特殊的方法,称为 prefetch():

query = Person.select().order_by(Person.name).prefetch(Pet)

for person in query:

    print(person.name)

    for pet in person.pets:

        print("  *", pet.name)

# prints:

# Bob

#   * Kitty

#   * Fido

# Grandma L.

# Herb

#   * Mittens Jr


            
            

本博客源码Github地址:

https://github.com/whisnos/myblog

请随手给个star,谢谢!

打赏

评论