地点

说明

过滤前一阶段的文档,仅返回条件计算结果为 true 的文档。

语法

where(condition: Expr)

示例

创建一个包含以下文档的 cities 集合:

Node.js

await db.collection('cities').doc('SF').set({name: 'San Francisco', state: 'CA', country: 'USA', population: 870000});
await db.collection('cities').doc('LA').set({name: 'Los Angeles', state: 'CA', country: 'USA', population: 3970000});
await db.collection('cities').doc('NY').set({name: 'New York', state: 'NY', country: 'USA', population: 8530000});
await db.collection('cities').doc('TOR').set({name: 'Toronto', state: null, country: 'Canada', population: 2930000});
await db.collection('cities').doc('MEX').set({name: 'Mexico City', state: null, country: 'Mexico', population: 9200000});

执行等值搜索:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .where(field("state").equals("CA"))
  .execute();

生成以下结果:

{name: 'San Francisco', state: 'CA', country: 'USA', population: 870000},
{name: 'Los Angeles',   state: 'CA', country: 'USA', population: 3970000}

行为

多个阶段

多个 where(...) 阶段可以链接在一起,充当每个条件中的 and(...) 表达式。

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .where(field("location.country").equals("USA"))
  .where(field("population").greaterThan(500000))
  .execute();

虽然需要根据两个条件的逻辑 or 进行过滤,但需要作为单个 where(...) 阶段来完成。

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .where(field("location.state").equals("NY").or(field("location.state").equals("CA")))
  .execute();

复杂表达式

过滤条件可以包含深度嵌套的表达式和逻辑运算符,从而构成复杂的过滤逻辑。例如:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .where(
    field("name").like("San%")
    .or(
      field("location.state").charLength().greaterThan(7)
      .and(field("location.country").equals("USA"))))

根据正则表达式过滤 /cities,或者在城市位于州名称足够长的 USA 中时进行过滤。您可以将任何表达式指定为条件,但只有计算结果为 true 的表达式才会匹配。

阶段顺序

阶段的顺序非常重要,因为它会改变查询评估顺序。例如,以下查询:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .limit(10)
  .where(field("location.country").equals("USA"))
  .execute();

只会对一组(可能随机)10 个文档应用 location.country 过滤条件,因为前面的 limit(...) 阶段已经限制了后续 where(...) 阶段能够接收的文档数量。鉴于此,经验法则是尽可能早地在查询中放置 where(...) 阶段。

类似 HAVING 的功能

where(...) 阶段可以位于任何更改文档架构的阶段(例如 select(...)aggregate(...))之后,并将引用这些阶段生成的字段。重点在于,对于 aggregate(...) 阶段而言,其后跟随的、引用已聚合字段的 where(...) 子句,其作用类似于标准 SQL 中的 HAVING 子句。例如:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .aggregate({
    accumulators: [field("population").sum().as("total_population")],
    groups: ['location.state']
  })
  .where(field("total_population").greaterThan(10000000))

可以返回那些城市总人口超过特定规模的州。

更多示例

Web

let results;

results = await execute(db.pipeline().collection("books")
  .where(field("rating").equal(5))
  .where(field("published").lessThan(1900))
);

results = await execute(db.pipeline().collection("books")
  .where(and(field("rating").equal(5), field("published").lessThan(1900)))
);
Swift
var results: Pipeline.Snapshot

results = try await db.pipeline().collection("books")
  .where(Field("rating").equal(5))
  .where(Field("published").lessThan(1900))
  .execute()

results = try await db.pipeline().collection("books")
  .where(Field("rating").equal(5) && Field("published").lessThan(1900))
  .execute()

Kotlin

var results: Task<Pipeline.Snapshot>

results = db.pipeline().collection("books")
    .where(field("rating").equal(5))
    .where(field("published").lessThan(1900))
    .execute()

results = db.pipeline().collection("books")
    .where(Expression.and(field("rating").equal(5),
      field("published").lessThan(1900)))
    .execute()

Java

Task<Pipeline.Snapshot> results;

results = db.pipeline().collection("books")
    .where(field("rating").equal(5))
    .where(field("published").lessThan(1900))
    .execute();

results = db.pipeline().collection("books")
    .where(Expression.and(
        field("rating").equal(5),
        field("published").lessThan(1900)
    ))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import And, Field

results = (
    client.pipeline()
    .collection("books")
    .where(Field.of("rating").equal(5))
    .where(Field.of("published").less_than(1900))
    .execute()
)

results = (
    client.pipeline()
    .collection("books")
    .where(And(Field.of("rating").equal(5), Field.of("published").less_than(1900)))
    .execute()
)