Dove

Descrizione

Filtra i documenti della fase precedente, restituendo solo quelli in cui la condizione restituisce true.

Esempi

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()
)
Java
Pipeline.Snapshot results1 =
    firestore
        .pipeline()
        .collection("books")
        .where(field("rating").equal(5))
        .where(field("published").lessThan(1900))
        .execute()
        .get();

Pipeline.Snapshot results2 =
    firestore
        .pipeline()
        .collection("books")
        .where(and(field("rating").equal(5), field("published").lessThan(1900)))
        .execute()
        .get();
Vai
results1, err := client.Pipeline().
	Collection("books").
	Where(firestore.FieldOf("rating").Equal(5)).
	Where(firestore.FieldOf("published").LessThan(1900)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

results2, err := client.Pipeline().
	Collection("books").
	Where(firestore.And(
		firestore.FieldOf("rating").Equal(5),
		firestore.FieldOf("published").LessThan(1900),
	)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

Comportamento

Filtri concatenati e nidificati

È possibile concatenare più fasi where(...), il che equivale logicamente a combinare le condizioni del filtro all'interno di una singola fase where(...) utilizzando un'espressione and(...). Entrambi gli approcci producono lo stesso piano di esecuzione e non hanno alcun impatto sull'esecuzione o sul rendimento delle query.

Ad esempio, concatenando più fasi where(...):

Node.js

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

equivale a utilizzare una singola fase where(...) con un and(...) composto:

Node.js

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

Tuttavia, il filtro basato su un or(...) logico di condizioni non può essere suddiviso in più fasi e deve essere eseguito in una singola fase where(...):

Node.js

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

Espressioni complesse

La condizione di filtro può contenere condizioni di filtro complesse contenenti espressioni e operatori logici nidificati in profondità. Ad esempio:

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"))))

filtri /cities in base a un'espressione regolare o se la città si trova in USA con un nome dello stato sufficientemente lungo. Come condizione può essere specificata qualsiasi espressione, ma verranno abbinate solo quelle che restituiscono il valore true.

Ordine delle fasi

L'ordine delle fasi è importante perché può modificare l'ordine di valutazione della query. Ad esempio, la query

Node.js

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

filtrerà solo in base a location.country per un insieme (potenzialmente casuale) di 10 documenti, in quanto la fase precedente limit(...) limita i documenti che vengono forniti alla fase where(...). Per questo motivo, la regola generale è di inserire le fasi where(...) il prima possibile nella query.

Funzionalità simili a HAVING:

La fase where(...) può essere eseguita dopo qualsiasi fase che modifichi lo schema dei documenti, come select(...) o aggregate(...), e farà riferimento ai campi prodotti da queste fasi. È importante notare che per aggregate(...), una clausola where(...) che fa riferimento ai campi accumulati si comporta come una clausola HAVING in un tipico sistema SQL. Ad esempio:

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))

consente di restituire gli stati con città con una popolazione totale superiore a una determinata dimensione.