Sfondo
Le operazioni di pipeline forniscono una nuova interfaccia di query per
Cloud Firestore che supporta funzionalità di query avanzate ed espressioni complesse
Introduce molte nuove funzioni, tra cui min(...), max(...), substring(...), regex_match(...) e array_contains_all(...), e fasi per eseguire trasformazioni complesse.
Per iniziare
Per installare e inizializzare gli SDK client, consulta le istruzioni nelle seguenti guide:
- Inizia a utilizzare gli SDK per dispositivi mobili e web.
- Inizia a utilizzare le librerie client server.
Sintassi
Le sezioni che seguono forniscono una panoramica della sintassi per le operazioni di pipeline.
Concetti
Una differenza notevole con le operazioni di pipeline è l'introduzione dell'ordinamento esplicito delle "fasi". In questo modo è possibile esprimere query più complesse. Tuttavia, si tratta di una deviazione notevole dall'interfaccia di query esistente che utilizza le operazioni principali, in cui l'ordinamento delle fasi era implicito. Considera il seguente esempio di operazioni di pipeline:
Web
const pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the // pipeline would have unintentional results. .limit(10);
Swift
let pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(Field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort([Field("name").ascending()]) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Kotlin
val pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Java
Pipeline pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10);
Python
from google.cloud.firestore_v1.pipeline_expressions import Field pipeline = ( client.pipeline() .collection("cities") .where(Field.of("population").greater_than(100_000)) .sort(Field.of("name").ascending()) .limit(10) )
Inizializzazione
Le operazioni di pipeline hanno una sintassi molto familiare proveniente dalle query Cloud Firestore esistenti. Per iniziare, inizializza una query scrivendo quanto segue:
Web
const { getFirestore } = require("firebase/firestore"); const { execute } = require("firebase/firestore/pipelines"); const database = getFirestore(app, "enterprise"); const pipeline = database.pipeline();
Swift
let firestore = Firestore.firestore(database: "enterprise") let pipeline = firestore.pipeline()
Kotlin
val firestore = Firebase.firestore("enterprise") val pipeline = firestore.pipeline()
Java
FirebaseFirestore firestore = FirebaseFirestore.getInstance("enterprise"); PipelineSource pipeline = firestore.pipeline();
Python
firestore_client = firestore.client(default_app, "your-new-enterprise-database") pipeline = firestore_client.pipeline()
Struttura
Esistono alcuni termini importanti da comprendere quando crei operazioni di pipeline: fasi, espressioni e funzioni.

Fasi: una pipeline può essere costituita da una o più fasi. A livello logico, queste rappresentano la serie di passaggi (o fasi) eseguiti per eseguire la query. Nota: in pratica, le fasi possono essere eseguite in ordine diverso per migliorare il rendimento. Tuttavia, questo non modifica l'intento o la correttezza della query.
Espressioni: le fasi spesso accettano un'espressione che consente di esprimere query più complesse. L'espressione può essere semplice e consistere in una singola funzione come eq("a", 1). Puoi anche esprimere espressioni più complesse nidificando espressioni come and(eq("a", 1), eq("b", 2)).
Riferimenti a campi e costanti
Le operazioni di pipeline supportano espressioni complesse. Pertanto, potrebbe essere necessario distinguere se un valore rappresenta un campo o una costante. Considera l'esempio seguente:
Web
const pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Swift
let pipeline = db.pipeline() .collection("cities") .where(Field("name").equal(Constant("Toronto")))
Kotlin
val pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")))
Java
Pipeline pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Python
from google.cloud.firestore_v1.pipeline_expressions import Field, Constant pipeline = ( client.pipeline() .collection("cities") .where(Field.of("name").equal(Constant.of("Toronto"))) )
Fasi
Fasi di input
La fase di input rappresenta la prima fase di una query. Definisce l'insieme iniziale di documenti su cui stai eseguendo la query. Per le operazioni di pipeline, questo è in gran parte simile alle query esistenti, in cui la maggior parte delle query inizia con una fase collection(...) o collection_group(...). Due nuove fasi di input sono database() e documents(...), dove database() consente di restituire tutti i documenti nel database, mentre documents(...) si comporta in modo identico a una lettura batch.
Web
let results; // Return all restaurants in San Francisco results = await execute(db.pipeline().collection("cities/sf/restaurants")); // Return all restaurants results = await execute(db.pipeline().collectionGroup("restaurants")); // Return all documents across all collections in the database (the entire database) results = await execute(db.pipeline().database()); // Batch read of 3 documents results = await execute(db.pipeline().documents([ doc(db, "cities", "SF"), doc(db, "cities", "DC"), doc(db, "cities", "NY") ]));
Swift
var results: Pipeline.Snapshot // Return all restaurants in San Francisco results = try await db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = try await db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = try await db.pipeline().database().execute() // Batch read of 3 documents results = try await db.pipeline().documents([ db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ]).execute()
Kotlin
var results: Task<Pipeline.Snapshot> // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute() // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute()
Java
Task<Pipeline.Snapshot> results; // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute(); // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute(); // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute(); // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute();
Python
# Return all restaurants in San Francisco results = client.pipeline().collection("cities/sf/restaurants").execute() # Return all restaurants results = client.pipeline().collection_group("restaurants").execute() # Return all documents across all collections in the database (the entire database) results = client.pipeline().database().execute() # Batch read of 3 documents results = ( client.pipeline() .documents( client.collection("cities").document("SF"), client.collection("cities").document("DC"), client.collection("cities").document("NY"), ) .execute() )
Come per tutte le altre fasi, l'ordine dei risultati di queste fasi di input non è stabile. Se è necessario un ordinamento specifico, è sempre necessario aggiungere un operatore sort(...).
Dove
La fase where(...) funge da operazione di filtro tradizionale sui documenti generati dalla fase precedente e rispecchia principalmente la sintassi "where" esistente per le query esistenti. Qualsiasi documento per cui un'espressione specificata restituisce un valore non true viene filtrato dai documenti restituiti.
È possibile concatenare più istruzioni where(...), che fungono da espressione and(...). Ad esempio, le due query seguenti sono logicamente equivalenti e possono essere utilizzate in modo intercambiabile.
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() )
Seleziona / aggiungi e rimuovi campi
Le fasi select(...), add_fields(...) e remove_fields(...) consentono di modificare i campi restituiti da una fase precedente. Queste tre fasi sono generalmente denominate fasi di tipo proiezione.
Le fasi select(...) e add_fields(...) consentono di specificare il risultato di un'espressione in un nome di campo fornito dall'utente. La fase select(...) restituisce solo i documenti con i nomi dei campi specificati, mentre add_fields(...) estende lo schema della fase precedente (sovrascrivendo potenzialmente i valori con nomi di campi identici).
La fase remove_fields(...) consente di specificare un insieme di campi da rimuovere dalla fase precedente. La specifica di nomi di campi inesistenti è un'operazione no-op.
Consulta la sezione Limita i campi da restituire di seguito, ma in generale l'utilizzo di una fase di questo tipo per limitare il risultato solo ai campi necessari nel client è utile per ridurre il costo e la latenza per la maggior parte delle query.
Aggrega / distingui
La fase aggregate(...) consente di eseguire una serie di aggregazioni sui documenti di input. Per impostazione predefinita, tutti i documenti vengono aggregati insieme, ma è possibile fornire un argomento grouping facoltativo, che consente di aggregare i documenti di input in bucket diversi.
Web
const results = await execute(db.pipeline() .collection("books") .aggregate( field("rating").average().as("avg_rating") ) .distinct(field("genre")) );
Swift
let results = try await db.pipeline() .collection("books") .aggregate([ Field("rating").average().as("avg_rating") ], groups: [ Field("genre") ]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .aggregate( AggregateStage .withAccumulators(AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre")) ) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .aggregate(AggregateStage .withAccumulators( AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre"))) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .aggregate( Field.of("rating").average().as_("avg_rating"), groups=[Field.of("genre")] ) .execute() )
Se groupings non è specificato, questa fase produce un solo documento, altrimenti viene generato un documento per ogni combinazione univoca di valori groupings.
La fase distinct(...) è un operatore di aggregazione semplificato che consente di generare solo i groupings univoci senza accumulatori. Si comporta in modo identico a aggregate(...) in tutti gli altri aspetti. Di seguito è riportato un esempio:
Web
const results = await execute(db.pipeline() .collection("books") .distinct( field("author").toUpper().as("author"), field("genre") ) );
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .distinct(Field.of("author").to_upper().as_("author"), "genre") .execute() )
Funzioni
Le funzioni sono un componente di base per la creazione di espressioni e query complesse. Per un elenco completo delle funzioni con esempi, consulta il riferimento alle funzioni. Per un breve riepilogo, considera la struttura di una query tipica:

Molte fasi accettano espressioni che contengono una o più funzioni. L'utilizzo più comune delle funzioni si trova nelle fasi where(...) e select(...). Esistono due tipi principali di funzioni che devi conoscere:
Web
let results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = await execute(db.pipeline().collection("books") .select(field("current").logicalMinimum(field("updated")).as("price_min")) ); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = await execute(db.pipeline().collection("books") .aggregate(field("price").minimum().as("min_price")) );
Swift
var results: Pipeline.Snapshot // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = try await db.pipeline().collection("books") .select([ Field("current").logicalMinimum(["updated"]).as("price_min") ]) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = try await db.pipeline().collection("books") .aggregate([Field("price").minimum().as("min_price")]) .execute()
Kotlin
var results: Task<Pipeline.Snapshot> // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute()
Java
Task<Pipeline.Snapshot> results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute(); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field # Type 1: Scalar (for use in non-aggregation stages) # Example: Return the min store price for each book. results = ( client.pipeline() .collection("books") .select( Field.of("current").logical_minimum(Field.of("updated")).as_("price_min") ) .execute() ) # Type 2: Aggregation (for use in aggregate stages) # Example: Return the min price of all books. results = ( client.pipeline() .collection("books") .aggregate(Field.of("price").minimum().as_("min_price")) .execute() )
Limiti
Nella maggior parte dei casi, la versione Enterprise non impone limiti alla forma della query. In altre parole, non sei limitato a un numero ridotto di valori in una query IN o OR. Esistono invece due limiti principali di cui devi essere a conoscenza:
- Scadenza: 60 secondi (identica alla versione Standard).
- Utilizzo della memoria: limite di 128 MiB sulla quantità di dati materializzati durante l'esecuzione della query.
Errori
Potresti riscontrare query non riuscite per diversi motivi. Ecco un link agli errori comuni e all'azione associata che puoi intraprendere:
| Codice di errore | Azione |
DEADLINE_EXCEEDED
|
La query che stai eseguendo supera il limite di 60 secondi e richiede un'ulteriore ottimizzazione. Per suggerimenti, consulta la sezione sul rendimento. Se non riesci a individuare la causa principale del problema, contatta il team. |
RESOURCE_EXHAUSTED
|
La query che stai eseguendo supera i limiti di memoria e richiede un'ulteriore ottimizzazione. Per suggerimenti, consulta la sezione sul rendimento. Se non riesci a individuare la causa principale del problema, contatta il team. |
INTERNAL
|
Contatta il team per ricevere assistenza. |
Rendimento
I database della versione Enterprise non richiedono che sia sempre presente un indice.
Ciò significa che una query può mostrare una latenza maggiore rispetto alle query esistenti, che avrebbero generato immediatamente un errore FAILED_PRECONDITION di indice mancante. Per migliorare il rendimento delle operazioni di pipeline, puoi seguire alcuni passaggi.
Crea indici
Indice utilizzato
Query Explain consente di identificare se la query viene gestita da un indice o se viene eseguita un'operazione meno efficiente, come una scansione della tabella. Se la query non viene gestita completamente da un indice, puoi crearne uno seguendo le istruzioni.
Creazione di indici
Puoi seguire la documentazione esistente sulla gestione degli indici per creare gli indici. Prima di creare un indice, acquisisci familiarità con le best practice generali per gli indici in Cloud Firestore. Per assicurarti che la query possa utilizzare gli indici, segui le best practice per creare indici con i campi nel seguente ordine:
- Tutti i campi che verranno utilizzati nei filtri di uguaglianza (in qualsiasi ordine)
- Tutti i campi su cui verrà eseguito l'ordinamento (nello stesso ordine)
- Campi che verranno utilizzati nei filtri di intervallo o di disuguaglianza in ordine decrescente di selettività dei vincoli di query
Ad esempio, per la query seguente,
Web
const results = await execute(db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("published").lessThan(1900)) .where(Field("genre").equal("Science Fiction")) .where(Field("rating").greaterThan(4.3)) .sort([Field("published").descending()]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("published").less_than(1900)) .where(Field.of("genre").equal("Science Fiction")) .where(Field.of("rating").greater_than(4.3)) .sort(Field.of("published").descending()) .execute() )
L'indice consigliato è un indice con ambito di raccolta su books per (genre [...], published DESC, avg_rating DESC).
Densità dell'indice
Cloud Firestore supporta indici sparsi e non sparsi. Per ulteriori informazioni, consulta Densità dell'indice.
Query coperte + indici secondari
Cloud Firestore può saltare il recupero del documento completo e restituire solo i risultati dall'indice se tutti i campi restituiti sono presenti in un indice secondario. In genere, questo comporta un miglioramento significativo della latenza (e del costo). Utilizzando la query di esempio riportata di seguito:
Web
const results = await execute(db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("category").like("%fantasy%")) .where(Field("title").exists()) .where(Field("author").exists()) .select([Field("title"), Field("author")]) .execute()
Kotlin
val results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("category").like("%fantasy%")) .where(Field.of("title").exists()) .where(Field.of("author").exists()) .select("title", "author") .execute() )
Se il database ha già un indice con ambito di raccolta su books per (category [...], title [...], author [...]), può evitare di recuperare qualsiasi elemento dai documenti principali. In questo caso, l'ordine nell'indice non ha importanza, [...] viene utilizzato per indicarlo.
Limita i campi da restituire
Per impostazione predefinita, una Cloud Firestore query restituisce tutti i campi di un documento, in modo analogo a un SELECT * nei sistemi tradizionali. Se, tuttavia, la tua applicazione ha bisogno solo di un sottoinsieme dei campi, puoi utilizzare le fasi select(...) o restrict(...) per eseguire il push di questo filtro lato server. In questo modo, si riduce sia la dimensione della risposta (diminuendo il costo di traffico in uscita della rete) sia la latenza.
Strumenti per la risoluzione dei problemi
Spiegazione query
Query Explain consente di visualizzare le metriche di esecuzione e i dettagli sugli indici utilizzati.
Metriche
Le operazioni di pipeline sono completamente integrate con le metriche Cloud Firestoreesistenti.
Problemi noti / limitazioni
Indici specializzati
Le operazioni di pipeline non supportano ancora i tipi di indice array-contains & vector esistenti. Anziché rifiutare semplicemente queste query, Cloud Firestore tenterà di utilizzare altri indici ascending & descending esistenti. Si prevede che durante l'anteprima privata le operazioni di pipeline con espressioni array_contains o find_nearest di questo tipo saranno più lente rispetto alle loro equivalenti esistenti a causa di questo.
Impaginazione
Il supporto per l'impaginazione semplice di un insieme di risultati non è supportato durante l'anteprima privata. Puoi aggirare questo problema concatenando le fasi equivalenti where(...) e sort(...) come mostrato di seguito.
Web
// Existing pagination via `startAt()` const q = query(collection(db, "cities"), orderBy("population"), startAt(1000000)); // Private preview workaround using pipelines const pageSize = 2; const pipeline = db.pipeline() .collection("cities") .select("name", "population", "__name__") .sort(field("population").descending(), field("__name__").ascending()); // Page 1 results let snapshot = await execute(pipeline.limit(pageSize)); // End of page marker const lastDoc = snapshot.results[snapshot.results.length - 1]; // Page 2 results snapshot = await execute( pipeline .where( or( and( field("population").equal(lastDoc.get("population")), field("__name__").greaterThan(lastDoc.ref) ), field("population").lessThan(lastDoc.get("population")) ) ) .limit(pageSize) );
Swift
// Existing pagination via `start(at:)` let query = db.collection("cities").order(by: "population").start(at: [1000000]) // Private preview workaround using pipelines let pipeline = db.pipeline() .collection("cities") .where(Field("population").greaterThanOrEqual(1000000)) .sort([Field("population").descending()])
Kotlin
// Existing pagination via `startAt()` val query = db.collection("cities").orderBy("population").startAt(1000000) // Private preview workaround using pipelines val pipeline = db.pipeline() .collection("cities") .where(field("population").greaterThanOrEqual(1000000)) .sort(field("population").descending())
Java
// Existing pagination via `startAt()` Query query = db.collection("cities").orderBy("population").startAt(1000000); // Private preview workaround using pipelines Pipeline pipeline = db.pipeline() .collection("cities") .where(field("population").greaterThanOrEqual(1000000)) .sort(field("population").descending());
Python
from google.cloud.firestore_v1.pipeline_expressions import Field # Existing pagination via `start_at()` query = ( client.collection("cities") .order_by("population") .start_at({"population": 1_000_000}) ) # Private preview workaround using pipelines pipeline = ( client.pipeline() .collection("cities") .where(Field.of("population").greater_than_or_equal(1_000_000)) .sort(Field.of("population").descending()) )
Supporto dell'emulatore
L'emulatore non supporta le operazioni di pipeline.
Supporto in tempo reale e offline
Le operazioni di pipeline non hanno ancora funzionalità in tempo reale e offline.
Passaggi successivi
- Inizia a esplorare la documentazione di riferimento per le funzioni e le fasi.