Indextypen in Cloud Firestore

Indizes sind ein wichtiger Faktor für die Leistung einer Datenbank. Ähnlich wie der Index eines Buches, der Themen in einem Buch Seitenzahlen zuordnet, ordnet ein Datenbankindex die Elemente in einer Datenbank ihren Positionen in der Datenbank zu. Wenn Sie einer Datenbank eine Abfrage senden, kann die Datenbank einen Index verwenden, um schnell die Speicherorte der angeforderten Elemente nachzuschlagen.

Diese Seite beschreibt die zwei Arten von Indizes , die Cloud - Firestor verwendet, Einfeld-Indizes und zusammengesetzten Indizes .

Ein Index hinter jeder Abfrage

Wenn für eine Abfrage kein Index vorhanden ist, durchsuchen die meisten Datenbanken ihren Inhalt Element für Element, ein langsamer Prozess, der sich mit zunehmendem Datenbankwachstum noch verlangsamt. Cloud Firestor garantieren eine hohe Abfrageleistung von Indizes für alle Abfragen. Daher hängt die Abfrageleistung von der Größe der Ergebnismenge und nicht von der Anzahl der Elemente in der Datenbank ab.

Weniger Indexmanagement, mehr App-Entwicklung

Cloud Firestore enthält Funktionen, die den Zeitaufwand für die Verwaltung von Indizes reduzieren. Die für die grundlegendsten Abfragen erforderlichen Indizes werden automatisch für Sie erstellt. Wie Sie Ihre App nutzen und testen, Wolke Firestor helfen Sie , zu identifizieren und zusätzliche Indizes erstellen Ihre Anwendung erfordert.

Indextypen

Cloud Firestor verwenden zwei Arten von Indizes: Einfeld und Composite. Abgesehen von der Anzahl der indizierten Felder unterscheiden sich Einzelfeld- und zusammengesetzte Indizes in der Art und Weise, wie Sie sie verwalten.

Einzelfeld-Indizes

Ein Einzelfeldindex speichert eine sortierte Zuordnung aller Dokumente in einer Sammlung, die ein bestimmtes Feld enthalten. Jeder Eintrag in einem Einzelfeldindex zeichnet den Wert eines Dokuments für ein bestimmtes Feld und die Position des Dokuments in der Datenbank auf. Cloud Firestore verwendet diese Indizes, um viele grundlegende Abfragen auszuführen. Sie verwalten Einzelfeld-Indizes, indem Sie die automatischen Indexierungseinstellungen und Indexausnahmen Ihrer Datenbank konfigurieren.

Automatische Indizierung

Standardmäßig verwaltet Cloud Firestore automatisch Einzelfeldindexe für jedes Feld in einem Dokument und jedes Unterfeld in einer Karte. Cloud Firestore verwendet die folgenden Standardeinstellungen für Einzelfeldindexe:

  • Für jedes nicht-Array und nicht-Karte Feld definiert Wolke Firestor zwei Sammel-scope Einfeld-Indizes, ein in aufsteigendem Modus und einen Modus in absteigender Reihenfolge.

  • Für jedes Kartenfeld erstellt Cloud Firestore einen aufsteigenden Index im Sammlungsbereich und einen absteigenden Index für jedes Nicht-Array- und Nicht-Zuordnungs-Unterfeld in der Karte.

  • Für jedes Array-Feld in einem Dokument erstellt und verwaltet Cloud Firestore einen Array-enthält-Index im Sammlungsbereich.

  • Einzelfeldindizes mit Sammlungsgruppenbereich werden standardmäßig nicht verwaltet.

Ausnahmen für Einzelfeld-Indexe

Sie können ein Feld von Ihren befreien automatische Indexierung Einstellungen durch einen Einzelfeld Index Befreiung zu schaffen. Eine Indexierungsausnahme überschreibt die datenbankweiten automatischen Indexeinstellungen. Eine Ausnahme kann einen Einzelfeldindex aktivieren, den Ihre Einstellungen für die automatische Indexierung andernfalls deaktivieren würden, oder einen Einzelfeldindex deaktivieren, den die automatische Indexierung ansonsten aktivieren würde. Für Fälle , in denen Ausnahmen von Nutzen sein können, finden Sie die Indizierung Best Practices .

Wenn Sie eine Einzelfeldindexausnahme für ein Kartenfeld erstellen, erben die Unterfelder der Karte diese Einstellungen. Sie können jedoch Einzelfeld-Indexausnahmen für bestimmte Unterfelder definieren. Wenn Sie eine Ausnahme für ein Unterfeld löschen, erbt das Unterfeld die Ausnahmeeinstellungen seines übergeordneten Elements, falls vorhanden, oder die datenbankweiten Einstellungen, wenn keine Ausnahmen für das übergeordnete Element vorhanden sind.

So erstellen und Einfeld-Index Ausnahmen zu verwalten, siehe Indizes in Cloud - Firestor verwalten .

Zusammengesetzte Indizes

Ein zusammengesetzter Index speichert eine sortierte Zuordnung aller Dokumente in einer Sammlung, basierend auf einer geordneten Liste von zu indexierenden Feldern.

Cloud Firestore verwendet zusammengesetzte Indizes, um Abfragen zu unterstützen, die noch nicht von Einzelfeld-Indexen unterstützt werden.

Cloud Firestore erstellt aufgrund der großen Anzahl möglicher Feldkombinationen nicht automatisch zusammengesetzte Indizes, wie dies bei Einzelfeldindexen der Fall ist. Stattdessen Wolke Firestor helfen Sie , zu identifizieren und erstellen erforderliche zusammengesetzte Indizes , wie Sie Ihre App bauen.

Wenn Sie die obige Abfrage versuchen, ohne zuerst den erforderlichen Index zu erstellen, gibt Cloud Firestore eine Fehlermeldung mit einem Link zurück, dem Sie folgen können, um den fehlenden Index zu erstellen. Dies geschieht jedes Mal, wenn Sie versuchen, eine Abfrage durchzuführen, die von einem Index nicht unterstützt wird. Sie können auch definieren und zu verwalten zusammengesetzte Indizes manuell von der Konsole oder durch die Verwendung von Firebase CLI . Weitere Informationen über das Erstellen und Verwalten von zusammengesetzten Indizes, siehe Verwalten von Indizes .

Indexmodi und Abfragebereiche

Sie konfigurieren Einzelfeld- und zusammengesetzte Indizes unterschiedlich, aber beide erfordern, dass Sie Indexmodi und Abfragebereiche für Ihre Indizes konfigurieren.

Indexmodi

Wenn Sie einen Index definieren, wählen Sie für jedes indizierte Feld einen Indexmodus aus. Der Indexmodus jedes Felds unterstützt spezifische Abfrageklauseln für dieses Feld. Sie können aus den folgenden Indexmodi wählen:

Indexmodus Beschreibung
aufsteigend Unterstützt < , <= , == , >= , > , und in Abfrageklauseln auf dem Feld und unterstützen Ergebnisse in aufsteigender Reihenfolge auf der Grundlage dieses Feldwert zu sortieren.
absteigend Unterstützt < , <= , == , >= , > , und in Abfrageklauseln auf dem Feld und unterstützen Ergebnisse in absteigender Reihenfolge auf diesem Gebiet Wert basierend Sortierung.
Array-enthält Träger - array-contains und array-contains-any Abfrageklauseln auf dem Feld.

Abfragebereiche

Jeder Index ist entweder auf eine Sammlung oder eine Sammlungsgruppe beschränkt. Dies wird als Abfragebereich des Indexes bezeichnet:

Sammlungsumfang
Cloud Firestore erstellt standardmäßig Indexe mit Sammlungsbereich. Diese Indizes unterstützen Abfragen, die Ergebnisse aus einer einzelnen Sammlung zurückgeben.

Umfang der Sammlungsgruppe
Eine Sammlungsgruppe umfasst alle Sammlungen mit derselben Sammlungs-ID. Um eine ausführen Sammelgruppe Abfrage , dass die Renditen gefiltert oder die Ergebnisse einer Sammelgruppe bestellt, müssen Sie einen entsprechenden Index mit Sammelgruppenbereich erstellen.

Indizierungsbeispiel

Durch die automatische Erstellung von Einzelfeld-Indizes für Sie ermöglicht Cloud Firestore Ihrer Anwendung, die grundlegendsten Datenbankabfragen schnell zu unterstützen. Einfeld-Indizes können Sie einfache Abfragen ausführen basierend auf Feldwerten und den Komparatoren < , <= , == , >= , > , und in . Für Array - Felder, sie ermöglichen es Ihnen ausführen array-contains und array-contains-any Abfragen.

Betrachten Sie zur Veranschaulichung die folgenden Beispiele aus der Sicht der Indexerstellung. Das folgende Snippet erstellt ein paar city Dokumente in einer cities Sammlung und setzt name , state , country , capital , population und tags Felder für jedes Dokument:

Netz
var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });
citiesRef.doc("LA").set({
    name: "Los Angeles", state: "CA", country: "USA",
    capital: false, population: 3900000,
    regions: ["west_coast", "socal"] });
citiesRef.doc("DC").set({
    name: "Washington, D.C.", state: null, country: "USA",
    capital: true, population: 680000,
    regions: ["east_coast"] });
citiesRef.doc("TOK").set({
    name: "Tokyo", state: null, country: "Japan",
    capital: true, population: 9000000,
    regions: ["kanto", "honshu"] });
citiesRef.doc("BJ").set({
    name: "Beijing", state: null, country: "China",
    capital: true, population: 21500000,
    regions: ["jingjinji", "hebei"] });

Unter der Annahme der Standardeinstellungen für die automatische Indexierung aktualisiert Cloud Firestore einen aufsteigenden Einzelfeldindex pro Nicht-Array-Feld, einen absteigenden Einzelfeldindex pro Nicht-Array-Feld und einen Array-enthält Einzelfeldindex für das Array-Feld. Jede Zeile in der folgenden Tabelle stellt einen Eintrag in einem Einzelfeldindex dar:

Sammlung Feld indiziert Abfrageumfang
Städte Name Sammlung
Städte Zustand Sammlung
Städte Land Sammlung
Städte Kapital Sammlung
Städte Bevölkerung Sammlung
Städte Name Sammlung
Städte Zustand Sammlung
Städte Land Sammlung
Städte Kapital Sammlung
Städte Bevölkerung Sammlung
Städte array-contains Regionen Sammlung

Abfragen, die von Einzelfeld-Indizes unterstützt werden

Mit diesen automatisch erstellten Einzelfeld-Indizes können Sie einfache Abfragen wie die folgenden ausführen:

Netz
const stateQuery = citiesRef.where("state", "==", "CA");
const populationQuery = citiesRef.where("population", "<", 100000);
const nameQuery = citiesRef.where("name", ">=", "San Francisco");

Sie können auch schaffen in und Verbindung Gleichheit ( == ) Abfragen:

Netz
citiesRef.where('country', 'in', ["USA", "Japan", "China"])

// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
         .where("capital", "==", false)
         .where("state", "==", "CA")
         .where("population", "==", 860000)

Wenn Sie eine Verbindung Abfrage ausgeführt werden müssen , die eine Reihe Vergleich verwendet ( < , <= , > oder >= ) oder wenn Sie von einem anderen Feld zu sortieren , benötigen, müssen Sie einen erstellen Composite - Index für diese Abfrage.

Die array-contains Index ermöglicht es Ihnen , die zur Abfrage regions Array - Feld:

Netz
citiesRef.where("regions", "array-contains", "west_coast")
// array-contains-any and array-contains use the same indexes
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])

Von zusammengesetzten Indizes unterstützte Abfragen

Cloud Firestore verwendet zusammengesetzte Indizes, um zusammengesetzte Abfragen zu unterstützen, die noch nicht von Einzelfeld-Indexen unterstützt werden. Sie benötigen beispielsweise einen zusammengesetzten Index für die folgenden Abfragen:

Netz
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)
// in and == clauses use the same index
citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)

Diese Abfragen erfordern den folgenden zusammengesetzten Index. Da die Abfrage eine Gleichheit (verwendet == oder in ) für das country Feld, können Sie einen auf- oder absteigenden Index - Modus für dieses Feld. Standardmäßig wenden Ungleichheitsklauseln eine aufsteigende Sortierreihenfolge basierend auf dem Feld in der Ungleichheitsklausel an.

Sammlung Felder indiziert Abfrageumfang
Städte (oder ) Land, Bevölkerung Sammlung

Um die gleichen Abfragen laufen , aber mit einer absteigenden Sortierreihenfolge, benötigen Sie einen zusätzlichen Composite - Index in absteigender Richtung für population :

Netz
citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", ">", 690000)
         .orderBy("population", "desc")

citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)
         .orderBy("population", "desc")
Sammlung Felder indiziert Abfrageumfang
Städte Land, Bevölkerung Sammlung
Städte Land, Bevölkerung Sammlung

Sie müssen auch einen zusammengesetzten Index erstellen ein kombinieren array-contains oder array-contains-any Abfrage mit zusätzlichen Klauseln.

Netz
citiesRef.where("regions", "array-contains", "east_coast")
         .where("capital", "==", true)

// array-contains-any and array-contains use the same index
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])
         .where("capital", "==", true)
Sammlung Felder indiziert Abfrageumfang
Städte Array-Tags enthält, (oder ) Kapital Sammlung

Von Sammlungsgruppenindizes unterstützte Abfragen

Um einen Index mit Sammlung Gruppenbereich zu demonstrieren, stellen Sie sich einen hinzufügen landmarks zu einigen der Unter Sammlung city Dokumente:

Netz
var citiesRef = db.collection("cities");

citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Bridge",
    category : "bridge" });
citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Park",
    category : "park" });

citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Gallery of Art",
    category : "museum" });
citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Mall",
    category : "park" });

Unter Verwendung der folgenden Einfeld-Index mit Sammlungsbereich, können Sie eine einzelne Stadt abfragen landmarks Sammlung auf der Grundlage der category Feld:

Sammlung Felder indiziert Abfrageumfang
Sehenswürdigkeiten (oder ) Kategorie Sammlung
Netz
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")
citiesRef.doc("SF").collection("landmarks").where("category", "in", ["park", "museum"])

Stellen Sie sich nun vor, Sie möchten die Sehenswürdigkeiten in allen Städten abfragen. Um diese Abfrage auf der Sammelgruppe laufen aus allen landmarks Sammlungen, müssen Sie ermöglichen landmarks Einfeld-Index mit Sammlung Gruppenbereich:

Sammlung Felder indiziert Abfrageumfang
Sehenswürdigkeiten (oder ) Kategorie Sammlungsgruppe

Mit diesem Index aktiviert ist , können Sie die Abfrage landmarks Sammelgruppe:

Netz
var landmarksGroupRef = db.collectionGroup("landmarks");

landmarksGroupRef.where("category", "==", "park")
landmarksGroupRef.where("category", "in", ["park", "museum"])

Um eine Sammlungsgruppenabfrage auszuführen, die gefilterte oder geordnete Ergebnisse zurückgibt, müssen Sie einen entsprechenden Einzelfeld- oder zusammengesetzten Index mit Sammlungsgruppenbereich aktivieren. Sammlungsgruppenabfragen, die keine Ergebnisse filtern oder sortieren, erfordern jedoch keine zusätzlichen Indexdefinitionen.

Sie können beispielsweise die folgende Sammlungsgruppenabfrage ausführen, ohne einen zusätzlichen Index zu aktivieren:

Netz
db.collectionGroup("landmarks").get()

Indexeinträge

Ihr Projekt konfiguriert Indizes sowie die Struktur eines Dokuments, wirken sich sowohl auf die Indexeinträge für das Dokument, die letztlich zu dem zählen Indexeintrag Zählgrenze .

Hier ist ein Beispiel zur Veranschaulichung.

Dokumentieren

name : "San Francisco"
temperatures : {summer: 67, winter: 55}
neighborhoods : ["Mission", "Downtown", "Marina"]

Einzelfeld-Indizes

  • (Automatischer) Name ASC & DESC
  • (Automatische) Temperaturen ASC & DESC
  • (Automatische) Nachbarschaften Array enthält

Zusammengesetzte Indizes

  • Name ASC, Nachbarschaften ASC
  • Name DESC, Nachbarschaften ASC

Resultierende Indexeinträge

Diese Indexierungskonfiguration führt zu den folgenden 12 Indexeinträgen für das Dokument:

Index Eintrag
Name ASC & DESC Name: "San Francisco"
Temperaturen ASC & DESC Temperaturen.Sommer: 67
Temperaturen ASC & DESC temperaturen.winter: 55
Nachbarschaften Array Enthält Nachbarschaften: "Mission"
Nachbarschaften Array Enthält Stadtteile: "Innenstadt"
Nachbarschaften Array Enthält Nachbarschaften: "Marina"
Name ASC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Mission"
Name ASC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Downtown"
Name ASC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Marina"
Name DESC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Mission"
Name DESC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Downtown"
Name DESC, Nachbarschaften ASC Name: "San Francisco", Stadtteile: "Marina"

Indizes und Preise

Indizes tragen zu den Lagerkosten Ihrer Anwendung. Für mehr auf , wie Speichergröße für Indizes berechnet, siehe Indexeintrag Größe .

Die Vorteile der Indexzusammenführung nutzen

Obwohl Cloud Firestore für jede Abfrage einen Index verwendet, ist nicht unbedingt ein Index pro Abfrage erforderlich. Bei Abfragen mit mehrere Gleichheit ( == ) Klauseln und gegebenenfalls eine orderBy Klausel können Cloud - Firestor wiederverwenden vorhandene Indizes. Cloud Firestore kann die Indexe für einfache Gleichheitsfilter zusammenführen, um die zusammengesetzten Indizes zu erstellen, die für größere Gleichheitsabfragen benötigt werden.

Sie können die Indexierungskosten reduzieren, indem Sie Situationen identifizieren, in denen Sie die Indexzusammenführung nutzen können. Zum Beispiel vorstellen , ein restaurants - Sammlung für ein Restaurant Bewertung App:

  • Restaurants

    • burgerthyme

      name : "Burger Thyme"
      category : "burgers"
      city : "San Francisco"
      editors_pick : true
      star_rating : 4

Stellen Sie sich nun vor, diese App verwendet Abfragen wie die folgenden. Beachten Sie, dass die App nutzt Kombinationen Gleichheitsklauseln für category , city und editors_pick während immer durch aufsteigende Sortierung star_rating :

Netz
db.collection("restaurants").where("category", "==", "burgers")
                            .orderBy("star_rating")

db.collection("restaurants").where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==" "San Francisco")
                            .where("editors_pick", "==", true )
                            .orderBy("star_rating")

Sie können für jede Abfrage einen Index erstellen:

Sammlung Felder indiziert Abfrageumfang
Restaurants Kategorie, STAR_RATING Sammlung
Restaurants Stadt, STAR_RATING Sammlung
Restaurants Kategorie, Stadt, STAR_RATING Sammlung
Restaurants Kategorie, Stadt, editors_pick, STAR_RATING Sammlung

Als bessere Lösung können Sie die Anzahl der Indizes reduzieren, indem Sie die Möglichkeit von Cloud Firestore nutzen, Indizes für Gleichheitsklauseln zusammenzuführen:

Sammlung Felder indiziert Abfrageumfang
Restaurants Kategorie, STAR_RATING Sammlung
Restaurants Stadt, STAR_RATING Sammlung
Restaurants editors_pick, STAR_RATING Sammlung

Dieser Satz von Indizes ist nicht nur kleiner, sondern unterstützt auch eine zusätzliche Abfrage:

Netz
db.collection("restaurants").where("editors_pick", "==", true)
                            .orderBy("star_rating")

Indizierungsgrenzen

Die folgenden Beschränkungen gelten für Indizes. Für alle Quoten und Grenzen finden Quotas und Grenzen .

Grenze Einzelheiten
Maximale Anzahl zusammengesetzter Indizes für eine Datenbank 200
Maximale Anzahl von Einzelfeld-Indexausnahmen für eine Datenbank 200

Maximale Anzahl von Indexeinträgen für jedes Dokument

40.000

Die Anzahl der Indexeinträge ist die Summe aus Folgendem für ein Dokument:

  • Die Anzahl der Einzelfeld-Indexeinträge
  • Die Anzahl der zusammengesetzten Indexeinträge

Um zu sehen , wie Cloud - Firestor schalten sich ein Dokument und eine Reihe von Indizes in Indexeinträge finden Sie dieses Indexeintrag Zählung Beispiel .

Maximale Größe eines Indexeintrags

7,5 KiB

Um zu sehen , wie Cloud - Firestor Indexeintrag Größe berechnet, finden Sie Indexeintrag Größe .

Maximale Summe der Größen der Indexeinträge eines Dokuments

8 MiB

Die Gesamtgröße ist die Summe der folgenden Elemente für ein Dokument:

  • Die Summe der Größe der Einzelfeld-Indexeinträge eines Dokuments
  • Die Summe der Größe der zusammengesetzten Indexeinträge eines Dokuments
  • Maximale Größe eines indizierten Feldwerts

    1500 Byte

    Feldwerte über 1500 Byte werden abgeschnitten. Abfragen mit abgeschnittenen Feldwerten können inkonsistente Ergebnisse zurückgeben.

    Best Practices für die Indizierung

    Bei den meisten Apps können Sie sich auf die automatische Indizierung und die Fehlermeldungslinks verlassen, um Ihre Indizes zu verwalten. In den folgenden Fällen können Sie jedoch Ausnahmen für einzelne Felder hinzufügen:

    Fall Beschreibung
    Große String-Felder

    Wenn Sie ein Zeichenfolgenfeld haben, das häufig lange Zeichenfolgenwerte enthält, die Sie nicht für Abfragen verwenden, können Sie die Speicherkosten senken, indem Sie das Feld von der Indizierung ausnehmen.

    Hohe Schreibraten in eine Sammlung mit Dokumenten mit sequentiellen Werten

    Wenn Sie ein Feld indizieren, das zwischen Dokumenten in einer Sammlung sequentiell zu- oder abnimmt, z. B. einen Zeitstempel, beträgt die maximale Schreibrate für die Sammlung 500 Schreibvorgänge pro Sekunde. Wenn Sie keine Abfragen basierend auf dem Feld mit sequenziellen Werten durchführen, können Sie das Feld von der Indizierung ausnehmen, um dieses Limit zu umgehen.

    In einem IoT-Anwendungsfall mit einer hohen Schreibrate kann beispielsweise eine Sammlung, die Dokumente mit einem Zeitstempelfeld enthält, die Grenze von 500 Schreibvorgängen pro Sekunde erreichen.

    Große Array- oder Kartenfelder

    Große Array- oder Map-Felder können die Grenze von 40.000 Indexeinträgen pro Dokument erreichen. Wenn Sie keine Abfragen basierend auf einem großen Array oder Map-Feld durchführen, sollten Sie es von der Indizierung ausnehmen.