为什么GAE DataStore不支持对不同属性的多个不等式过滤器?

时间:2014-01-08 16:36:23

标签: google-app-engine google-cloud-datastore

我知道这是DataStore的限制,但我只想弄清楚原因。我读过bigtable文章,我找不到对不同列上的不等式过滤器的任何限制。它可以支持前缀和范围扫描。恕我直言,DataStore可以通过这两个操作支持多个不等式过滤器。你知道从DataStore获取功能的原因吗?

2 个答案:

答案 0 :(得分:7)

To avoid having to scan the entire index table, the query mechanism relies on 
all of a query's potential results being adjacent to one another in the index.
To satisfy this constraint, a single query may not use inequality comparisons 
(LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, NOT_EQUAL)
on more than one property across all of its filters

[来源:https://cloud.google.com/appengine/docs/standard/java/datastore/query-restrictions]

答案 1 :(得分:1)

每个数据存储区查询都在一个或多个索引表上运行。

在考虑不等式过滤器时,我们希望在最多一个属性上运行,以避免在整个索引表上运行。在调查过滤器如何工作,datastore-indexes.xml定义的方式以及索引的准确性时,它更容易掌握:

<datastore-index>是数据存储应维护的元素,每个索引一个元素。因此,您为实体的类型及其属性之间的每个关系定义一个索引(即表格)。现在想象一下,当你需要计算不同属性的多个不等式过滤器时?它可能导致巨大的运行时间。不好。

<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes autoGenerate="true">
    <datastore-index kind="Greeting" ancestor="true" source="manual">
        <property name="user" direction="asc" />
        <property name="birthYear" direction="asc" />
        <property name="height" direction="asc" />
    </datastore-index>

    <datastore-index kind="Greeting" ancestor="true" source="manual">
        <property name="date" direction="asc" />
    </datastore-index>
</datastore-indexes>

现在,让我们看看过滤器。 它是一个有效过滤器 - 他只在一个属性上运行(birthYear属性)。

Filter birthYearMinFilter =
  new FilterPredicate("birthYear",
                      FilterOperator.GREATER_THAN_OR_EQUAL,
                      minBirthYear);

Filter birthYearMaxFilter =
  new FilterPredicate("birthYear",
                      FilterOperator.LESS_THAN_OR_EQUAL,
                      maxBirthYear);

Filter birthYearRangeFilter =
  CompositeFilterOperator.and(birthYearMinFilter, birthYearMaxFilter);

Query q = new Query("Person").setFilter(birthYearRangeFilter);

它是无效过滤器,他在2个属性(birthYear和height)上运行:

Filter birthYearMinFilter =
  new FilterPredicate("birthYear",
                      FilterOperator.GREATER_THAN_OR_EQUAL,
                      minBirthYear);

Filter heightMaxFilter =
  new FilterPredicate("height",
                      FilterOperator.LESS_THAN_OR_EQUAL,
                      maxHeight);

Filter invalidFilter =
  CompositeFilterOperator.and(birthYearMinFilter, heightMaxFilter);

Query q = new Query("Person").setFilter(invalidFilter);