GAE 翻译(5)Queries and Indexes

Queries and Indexes

每个datastore 的查询都会用一个索引,它是一个表,按指定顺序包含了查询的结果。一个app engine 程序用一个 index.yaml 来定义索引。如果没有配置,开发服务器会在第一次执行查询的时候会给出索引建议,并写入这个文件。你可以在上传之前去更改这个文件配置。

以索引为基础的查询机制支持大部分类型的查询。但它不支持一些过去的传统数据库查询技术。下面介绍查询的一些限制,和他们的用法。

·          Introducing Queries

·          Introducing Indexes

·          Defining Indexes With index.yaml

·          Restrictions on Queries

Introducing Queries

查询从datastore 返回满足一系列条件的entitys。查询指定某一表类,不指定或指定多个属性的条件,不指定或指定多个排序方式。当查询被执行,它按指定的排序返回满足这些条件的entity

 

Datastore 编程接口提供2种方式来准备和执行查询:Query方式,通过类方法;GqlQuery方式,通过类似SQL 的语句来查询。在Creating, Getting and Deleting Data: Getting Entities Using a Query这小节里面,以及对应的reference 里面有详细介绍。

 

class Person(db.Model):
  first_name
= db.StringProperty()
  last_name
= db.StringProperty()
  city
= db.StringProperty()
  birth_year
= db.IntegerProperty()
  height
= db.IntegerProperty()

# The Query interface prepares a query using instance methods.
q
= Person.all()
q
.filter("last_name =", "Smith")
q
.filter("height <", 72)
q
.order("-height")

# The GqlQuery interface prepares a query using a GQL query string.
q
= db.GqlQuery("SELECT * FROM Person " +
               
"WHERE last_name = :1 AND height < :2 " +
               
"ORDER BY height DESC",
               
"Smith", 72)

# The query is not executed until results are accessed.
results
= q.fetch(5)
for p in results:
 
print "%s %s, %d inches tall" % (p.first_name, p.last_name, p.height)

Introducing Indexes

Appentine 为应用程序打算构造的所有查询维护一份索引。当修改了记录,索引随之改变。当应用程序执行查询,datastore从对应的索引里面直接返回记录。

 


应用程序为在query 里面使用的每个表类、过滤的字段、排序都有一个索引。考虑下面的查询:

 

SELECT * FROM Person WHERE last_name = "Smith"

                       AND height < 72

                     ORDER BY height DESC

这个查询的索引是一个存放key的表,为Person表类的heightlast_name 属性按height 倒序排列。

2个结构一样的查询,仅比较的参数值不一样,能够用一样的查询。例如下面的查询和上门的用一样的索引。

SELECT * FROM Person WHERE last_name = "Jones"

                       AND height < 63

                     ORDER BY height DESC

Datastore 按下面的步骤执行查询。

1.     

Datastore 按查询的表类,过滤,排序好识别索引。

2.     

Datastore index里面从第一个entity 开始扫描符合查询条件的所有记录。

3.     

Datastore 继续扫描索引,返回每个 entity,直到下一条记录不符合条件,或者到了最后记录。

 

       索引表包括了过滤条件和排序里面的所有属性,而每行按下面几个方面顺序排列。

·          祖先

·           =表达式里面的属性值

·           非=表达式里面的属性值

·           排序里面的所有值

This puts all results for every possible query that uses this index in consecutive rows in the table.

这种机制支持广泛的查询,适合所有的应用程序。然而,它可能不支持类似你以前使用的一些传统数据库的查询方式,例如:


提示,查询条件不能精确的部分匹配字符传,但你可以构造一个前缀使之利用不等查询。(意思就是没有like )
db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2", "abc", "abc" + "/xEF/xBF/xBD")

这样就匹配myModel表类的每个prop属性以abc 开始的所有记录。"/xEF/xBF/xBD"是对应一个最大可能的字符串。当属性值按索引排序,所有以该前缀开头的记录都落进这个范围内。

 

Defining Indexes With index.yaml

appEngine 默认为几个简单的查询构造索引。其它的查询,就必须在 index.yaml里面指定索引。如果程序执行的时候没有找到对应索引(既不能默认又没有在index.yaml)就会失败。

 

     Appengine 为下面几种查询自动索引

·         

只用了=表达式和祖先的过滤

·         

只用了非=过滤(只能用于单个属性)

·       

只有一个排序方式:升序

       其它类型的查询就要 index.yaml 了,包括

·         

用了倒序

·         

多重(属性)的排序

·       

又有等于又有非等于的条件

·         

既有非等于又有祖先的过滤条件

开发服务器是使得管理index.yaml 很容易:如果发现没有索引导致了查询失败,开发服务器会自动定义一个来保证查询成功。

 

如果你的程序本地测试用了各种各样复杂的查询形式,那么也会生成复杂的索引。如果你的测试并不是每个都真正要使用的,就可以在上传程序之前修改索引文件。

提示:如果dev_appserver.py启动的时候用了 –require_indexes 选项,indexYaml就不会产生,并在缺乏查询所需索引时产生异常。用这个选项测试你的程序检查你所需要的所有索引都齐备了。

index.yaml describes each index table, including the kind, the properties needed for the query filters and sort orders, and whether or not the query uses an ancestor clause (either Query.ancestor() or a GQL ANCESTOR IS clause). The properties are listed in the order they are to be sorted: properties used in equality filters first, followed by the property used in inequality filters, then the query results sort orders and their directions.
index.yaml
描述每个索引表,包括表类,过滤用到的属性和排序,和是否用了祖先子句(Query.ancestor() 或者 GQL ANCESTOR IS)。按照排序列出属性:用于等号的属性,用于非等号的属性,然后查询结果按这些顺序排序。


再次考虑下面的查询:

SELECT * FROM Person WHERE last_name = "Smith"

                       AND height < 72

                     ORDER BY height DESC

如果应用程序只执行这个查询(或者其它类似的,只是条件值不同),index.yaml 文件将看起来象这样

indexes:

- kind: Person

  properties:

  - name: last_name

  - name: height

    direction: desc

当一个entity创建了或者更新了,每个适当的索引就会被更新。一个表类的索引数量影响新增和修改的效率。

Restrictions on Queries

这种索引的天然机制导致了一些查询上面的限制。

Filtering Or Sorting On a Property Requires That the Property Exists

一个查询对某个属性的过滤条件或者排序暗示了entity的这个属性必须有值这样一个前提条件。


有时某个表类的某些记录的某个属性有值,而同类的其它记录没有。这样过滤条件就只作用于有值的属性。缺乏查询条件或者排序子句所需属性的值的entity将在查询的时候从索引里面删去。

 

No Filter That Matches Entities That Do Not Have a Property

不能查询没有某个属性的entity。一个取舍是创建一个固定属性给它一个缺省值None.然后创建查询条件=None.

 

Inequality Filters Are Allowed On One Property Only

一个查询中所有不等于的条件只能用于一个字段。

例如这样的GQL 是允许的

SELECT * FROM Person WHERE birth_year >= :min

                       AND birth_year <= :max

但是下面的GQL不允许,因为它在同一个查询多个属性都用了 不等于

SELECT * FROM Person WHERE birth_year >= :min_year

                       AND height >= :min_height     # ERROR

一个查询可以联合多个=用于多个属性。即使查询本身还有另外的不=条件。

SELECT * FROM Person WHERE last_name = :last_name

                       AND city = :city

                       AND birth_year >= :min_year

为了避免全表扫描,查询机制依赖于在索引表中所有查询结果互相接近。当所有结果都连续的时候,一个单索引表不能为多个属性表现多个不等于的过滤,

Properties In Inequality Filters Must Be Sorted Before Other Sort Orders

如果一个查询有不等于的子句以及一个或多个排序,那么排序子句必须包含这个不等的属性,并且排列在其它排序的前面。

这个GQL 是非法的,因为没有按birth_year排序

SELECT * FROM Person WHERE birth_year >= :min_year

                     ORDER BY last_name              # ERROR

Similarly, this GQL query is not valid because it does not order by the filtered property before ordering by other properties:

下面这个也不行因为birth_year 不是首要排序

SELECT * FROM Person WHERE birth_year >= :min_year

                     ORDER BY last_name, birth_year  # ERROR

This GQL query is valid:

SELECT * FROM Person WHERE birth_year >= :min_year

                     ORDER BY birth_year, last_name

一个不等式的查询,为了取回所有的结果,它会对索引表从第一行进行扫描,然后返回所有连续的结果直到找到不符合的。因为连续行表现了完整的结果,所以不等式的属性必须是第一个排序。

No Not-Equal Filter

Datastore 不支持 != 以后也许会支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值