使用範圍和不等式篩選條件查詢多個屬性總覽

Firestore (Datastore 模式) 支援在單一查詢中,對多個屬性使用範圍和不等式篩選器。這項功能可讓您對多個屬性設定範圍和不等式條件,並將後續篩選邏輯的實作作業委派給 Datastore 模式的 Firestore,簡化應用程式開發作業。

針對多個屬性使用範圍和不等式篩選條件

下列查詢會對優先順序和天數使用範圍篩選器,傳回優先順序大於 4 且完成期限少於 3 天的所有工作。

Go

query := datastore.NewQuery("Task").
   FilterField("priority", ">", 4).
   FilterField("days", "<", 3).

GQL

SELECT * FROM /tasks WHERE priority > 4 AND days < 3;

Java

Query<Entity> query =
    Query.newEntityQueryBuilder()
      .setKind("Task")
      .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("priority", 4), PropertyFilter.lt("days", 3)))
    .build();

Node.js

const query = datastore
  .createQuery('Task')
  .filter(
    and([
      new PropertyFilter('priority', '>', 4),
      new PropertyFilter('days', '<', 3),
    ])
  );

Python

from google.cloud import datastore
client = datastore.Client()
query = client.query(kind="Task")
query.add_filter(filter=PropertyFilter("priority", ">", 4))
query.add_filter(filter=PropertyFilter("days", "<", 3))

PHP

$query = $datastore->query()
    ->kind('Task')
    ->filter('priority', '>', 4)
    ->filter('days', '<', 3)

C#

Query query = new Query("Task")
{
  Filter = Filter.And(Filter.GreaterThan("priority", 4),
    Filter.LessThan("days", 3))
};

Ruby

query = datastore.query("Task")
                 .where("priority", ">", 4)
                 .where("days", "<", 3)

建立索引的注意事項

開始執行查詢前,請務必先閱讀查詢相關資訊。

如果未指定 ORDER BY 子句,Firestore (Datastore 模式) 會使用任何可滿足查詢篩選條件的索引來提供查詢結果。這種做法會產生根據索引定義排序的結果集。

如要盡可能提高 Datastore 模式 Firestore 查詢的效能和成本效益,請最佳化索引中的屬性順序。如要達成這個目標,請確保索引從左到右排序,讓查詢精簡為資料集,避免掃描多餘的索引項目。

舉例來說,假設您想在員工集合中搜尋薪資超過 $100,000 美元,且年資超過 0 年的美國員工。根據您對資料集的瞭解,您知道薪資限制比經驗限制更具選擇性。可減少索引掃描次數的索引是 (salary [...], experience [...]) 索引。因此,快速且具成本效益的查詢會先排序 salary,再排序 experience,如下例所示:

GQL

SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY salary, experience

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
    .setOrderBy(OrderBy("salary"), OrderBy("experience"))
    .build();

Node.js

const query = datastore
  .createQuery("employees")
  .filter(
    and([
      new PropertyFilter("salary", ">", 100000),
      new PropertyFilter("experience", ">", 0),
       ])
    )
  .order("salary")
  .order("experience");

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.add_filter("experience", ">", 0)
query.order = ["-salary", "-experience"]

最佳化索引的最佳做法

最佳化索引時,請注意下列最佳做法。

依等式排序查詢,然後依最具選擇性的範圍或不等式欄位排序

Firestore (Datastore 模式) 會使用複合索引最左側的屬性,來滿足 orderBy() 查詢第一個欄位的等式限制,以及範圍和不等式限制 (如有)。這些限制條件可減少 Firestore (Datastore 模式) 掃描的索引項目數量。Datastore 模式的 Firestore 會使用索引的其餘屬性,滿足查詢的其他範圍和不等式限制。這些限制不會減少 Firestore (Datastore 模式) 掃描的索引項目數量,但會篩除不相符的實體,減少傳回給用戶端的實體數量。

如要進一步瞭解如何建立有效率的索引,請參閱索引結構和定義,以及最佳化索引

依查詢限制選擇性遞減順序排列屬性

為確保 Firestore (Datastore 模式) 為查詢選取最佳索引,請指定 orderBy() 子句,根據查詢中限制的選擇性,排序範圍和不相等屬性,從選擇性最高的屬性開始。選擇性越高,相符的實體就越少;選擇性越低,相符的實體就越多。在索引排序中,將選擇性較高的範圍和不等比較屬性,放在選擇性較低的屬性之前。

為盡量減少 Firestore (Datastore 模式) 掃描並透過網路傳回的實體數量,您應一律按照查詢限制選擇性的遞減順序排序屬性。如果結果集並非依所需順序排列,且結果集預計很小,您可以實作用戶端邏輯,按照預期順序重新排序。

舉例來說,假設您想在員工集合中搜尋薪資超過 $100,000 美元的美國員工,並依員工年資排序結果,如果您預期只有少數員工的薪資會超過 $100,000 美元,則可採用下列有效率的查詢撰寫方式:

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(PropertyFilter.gt("salary", 100000))
    .setOrderBy(OrderBy("salary"))
    .build();
QueryResults<Entity> results = datastore.run(query);
// Order results by `experience`

Node.js

const query = datastore
  .createQuery("employees")
  .filter(new PropertyFilter("salary", ">", 100000))
  .order("salary");
const [entities] = await datastore.runQuery(query);
// Order results by `experience`

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.order = ["salary"]
results = query.fetch()
// Order results by `experience`

雖然在查詢中加入 experience 的排序條件會產生相同的實體集,並避免在用戶端重新排序結果,但查詢可能會讀取比先前查詢多出許多無關的索引項目。這是因為 Firestore (Datastore 模式) 一律會優先使用索引屬性前置字元與查詢的 order by 子句相符的索引。如果 experience 已新增至排序依據子句,則 Datastore 模式的 Firestore 會選取 (experience [...], salary [...]) 索引,用於計算查詢結果。由於 experience 沒有其他限制,Firestore (Datastore 模式) 會先讀取 employees 集合的所有索引項目,再套用 salary 篩選器,找出最終結果集。也就是說,系統仍會讀取不符合 salary 篩選條件的索引項目,進而增加查詢的延遲時間和費用。

定價

如果查詢針對多個屬性使用範圍和不等式篩選條件,系統會根據讀取的實體和索引項目計費。

詳情請參閱定價頁面。

限制

除了查詢限制外,使用查詢時,如果範圍和不等式篩選條件套用至多個屬性,請注意下列限制:

  • 為避免查詢作業耗費過多資源,Datastore 模式的 Firestore 將範圍或不等式運算子的數量限制為 10 個。

後續步驟