Skip to content

Latest commit

 

History

History
232 lines (152 loc) · 13.3 KB

firebase.mdx

File metadata and controls

232 lines (152 loc) · 13.3 KB
title Firebase
description Connect to Cloud Firestore and the Firebase Realtime Database, browse collections and nodes, and edit documents

import RegistryPlugin from "/snippets/registry-plugin.mdx";

One plugin serves two connection types. In Cloud Firestore a collection is a table and a document is a row. In Firebase Realtime Database the children of a node are the rows. Neither has SQL: the editor takes REST request lines such as GET users/alice.

Quick setup

Click New Connection…, select Cloud Firestore or Firebase Realtime Database, pick an Auth Method, then click Save & Connect.

With a service account key, leave Project ID empty: the key names the project. Leave Database URL empty as well, and the Realtime Database connection opens the project's default instance.

Connection settings

Field Shown for Notes
Auth Method Both Service Account Key (the default), Application Default Credentials, or Emulator (no credentials)
Service Account Key Service Account Key A path to the JSON key file, or the key JSON itself. Stored in the Keychain
Project ID Both Empty takes the project from the credentials
Database Cloud Firestore Empty means (default). The database switcher lists the project's other Firestore Native databases
Database URL Realtime Database https://<name>.firebaseio.com or https://<name>.<region>.firebasedatabase.app. Empty finds the project's default instance, and the database switcher lists the others
Emulator Host Emulator host:port of the emulator

Both are managed services, so any version works, and there is no host, port or SSH tunnel to set.

Connection URL

There is no URL scheme for Firebase. Create the connection from the form.

Authentication

Pick Service Account Key and generate a key in the Firebase console under Project settings, Service accounts. On a Mac where gcloud is already signed in, Application Default Credentials needs no file.

Auth Method What is sent
Service Account Key An OAuth token signed with the key
Application Default Credentials The token from gcloud auth application-default login, or from the key file GOOGLE_APPLICATION_CREDENTIALS names. An empty Project ID falls back to the project in that file, then to GOOGLE_CLOUD_PROJECT
Emulator (no credentials) The token owner, which the Firebase emulators treat as an administrator

Access comes from the account's IAM roles, not from security rules. Cloud Datastore Viewer reads Firestore and Cloud Datastore User also writes it. Firebase Realtime Database Viewer reads the Realtime Database and Firebase Realtime Database Admin also writes it.

Cloud Firestore

Browsing collections

The sidebar lists the root collections, then their subcollections as collection groups such as */orders, which reads every orders collection at any depth.

Every grid has __name__ first: the document ID, or the full path in a collection group. The other columns are the fields the documents on the page hold, in alphabetical order. A field a document lacks shows as No Field, not NULL. Maps and arrays show as JSON, a geopoint as latitude, longitude, and a reference as the path it points to.

Filtering and sorting

Filters and sorts run as one structured query. A filter value takes the type the field holds, so age = 30 matches the integer 30, and zip = 02134 matches the string when zip holds strings.

Operators What Firestore runs
equals, not equals EQUAL, NOT_EQUAL
greater than, greater or equal, less than, less or equal Range filters
in list, not in list IN, NOT_IN, with 1 to 30 values
between Two bounds, both inclusive
starts with A range from the prefix to the prefix followed by U+F8FF
contains ARRAY_CONTAINS, on an array field only
is NULL, is not NULL IS_NULL, IS_NOT_NULL

contains and not contains on a string field, ends with, the empty checks and REGEX are refused with the reason, since Firestore has no text search. Matching is always case-sensitive. Match any joins the rows with OR.

A raw filter row takes one Filter object from the Firestore REST API, which reaches nested fields: {"fieldFilter": {"field": {"fieldPath": "address.city"}, "op": "EQUAL", "value": {"stringValue": "Milan"}}}.

A sort on a field leaves out the documents that do not have it, and the row count leaves them out too.

Editing

Each saved change is one request:

Change Request
New row POST users?documentId=alice. With __name__ empty, Firestore generates the ID. In a collection group, __name__ is the full path, such as users/alice/orders/o1
Edited cells PATCH users/alice?updateMask=age, with only the fields you changed. It fails on a document deleted in the meantime instead of recreating it
Removed field The field in updateMask and not in the body
Deleted row DELETE users/alice

An edited cell keeps the type the field had: a string stays a string even when the new text is a number. A cell that held null, or no field, takes the type the column holds on other rows. Timestamps take RFC 3339 text such as 2026-10-12T08:00:00Z, geopoints 45.46, 9.19, bytes base64, and references a document path.

Edit Document opens the whole document as JSON. Types JSON lacks are written as one-key objects:

{
  "__name__": "users/alice",
  "age": 31,
  "since": {"$timestamp": "2026-10-12T08:00:00Z"},
  "owner": {"$ref": "teams/core"},
  "home": {"$geo": {"latitude": 45.46, "longitude": 9.19}},
  "avatar": {"$bytes": "aGk="},
  "ratio": {"$double": 2}
}

$double also takes "NaN", "Infinity" and "-Infinity". A map whose only key is one of these tags goes inside $map. Insert Document takes the same JSON, with __name__ as the ID or left out for a generated one.

Saving reads the document again and stops if it changed after you opened it, so another writer's change is never overwritten.

Request editor

Request What it does
GET users The first 100 documents of a collection. ?pageSize= sets another number
GET */orders Every orders collection at any depth
GET users/alice One document
GET / The root collection IDs. GET users/alice?collections lists a document's subcollections
QUERY {"structuredQuery": {...}} A structured query from the REST reference, with REST values such as {"integerValue": "30"}. QUERY users/alice {...} runs it under a document
POST users {"name": "Bob"} Creates a document with a generated ID. POST users?documentId=bob names it
PATCH users/alice?updateMask=age {"age": 31} Changes the named fields. Without updateMask the body replaces the document. Never creates one
DELETE users/alice Deletes a document

POST and PATCH bodies use the Edit Document JSON, on the same line or the lines under it. There is no PUT. Write a space or any of % ? # & = / inside an ID as its percent escape, such as GET users/John%20Doe. DELETE raises the dangerous query warning even on Silent. Other writes follow the connection's Safe Mode level.

Realtime Database

Browsing nodes

The sidebar lists /, the root, and the root's children when there are 500 or fewer. Open / for a root with more.

Every grid has $key first. Children that are objects add their fields as columns, and children that are plain values go in $value. Nested objects show as JSON. A node holding one plain value, such as /maintenance, shows one row with that path as its $key, and editing it writes the node itself.

Filtering and sorting

Filter on one column, $key, $value or a child field, and sort only by that column. The filter bar offers Match all only.

Operators What the Realtime Database runs
equals equalTo
greater than, greater or equal startAfter, startAt
less than, less or equal endBefore, endAt
between startAt and endAt
starts with startAt and endAt with U+F8FF
is NULL equalTo=null

Other operators are refused with the reason. Ordering by a child field needs .indexOn for it in the database rules.

A raw filter row takes a query string as written, such as orderBy="age"&startAt=18. When it names no limit, limitToFirst is added for the page, and orderBy="$key" too when it names no order.

Each page asks for every child up to the end of that page and drops the ones before it. Counting lists every key, so a grid shows no total until you click Count Exactly, and a filtered grid shows none at all.

Editing

Change Request
New row PUT under the $key you typed, replacing any child already there, or POST for a generated key
Edited cells PATCH on the child with the changed fields
Edited $value PUT on the child
Removed field The field set to null in the PATCH
Deleted row DELETE on the child

A key cannot be empty or contain ., #, $, [, ] or /.

Edit Document opens a child as {"$key": "<path>", "$value": <JSON>}. Saving reads the node again and writes only if it still matches what you opened. Insert Document takes the same shape, or bare JSON for a child under a generated key.

Request editor

GET /chats?orderBy="$key"&limitToFirst=20

GET, PUT, PATCH, POST and DELETE take a path and, for writes, a JSON body on the same line or the lines under it. Query parameters apply to GET only, and a PATCH body is an object of the children to change. PUT / and DELETE / are refused: write or delete the root's children one at a time.

A DELETE, a PUT that leaves the node empty and a PATCH that sets a child to null raise the dangerous query warning even on Silent. Other writes follow the connection's Safe Mode level.

Emulators

Pick Emulator (no credentials), enter the emulators' project as Project ID, and set Emulator Host to the Firestore or Database emulator. Unless firebase.json moves them, they listen on 127.0.0.1:8080 and 127.0.0.1:9000.

The Realtime Database connection opens the <project>-default-rtdb namespace. For another, set Database URL to http://127.0.0.1:9000/?ns=<name>.

SSL/TLS

Requests to Google are always HTTPS, and there is no SSL Mode. The emulators are plain HTTP.

Limitations

  • No real-time listeners. A grid shows what was read; refresh it to see later changes.
  • Firestore pages with offset, which Firestore bills as one read per skipped document. Filter to reach late rows rather than paging to them. Export reads with a cursor and skips nothing.
  • Realtime Database pages download every child before the page, so late pages of a large node are slow. Filter on $key to start further in.
  • Export fixes its columns from the first page. Fields that appear only later go into an __extra__ column as JSON.
  • Import is not available. Write documents from the request editor.
  • The Structure tab lists the fields of a 50-document sample and is read-only. A field few documents hold can be missing from it.
  • Datastore-mode databases are not listed. Use a Firestore Native database.
  • Collection groups come from the first two documents of up to 30 root collections, one level down, and the list is kept for 10 minutes. Read any other path from the request editor, such as GET users/alice/orders.
  • Not available on iPhone or iPad.

Troubleshooting

Permission denied: …

The account lacks the IAM role for the operation named after the colon. Grant one of the roles under Authentication, or connect with an account that has it.

Enter a Project ID, or use a service account key that names one.

A Firestore connection found no project: the Application Default Credentials file names none and GOOGLE_CLOUD_PROJECT is not set. Fill in Project ID.

Enter a Database URL or a Project ID.

A Realtime Database connection needs one of the two to find the instance. Fill in either.

"…" is not a Realtime Database URL.

Database URL is not a Firebase address. Copy it from the Realtime Database page of the Firebase console, or clear it to use the default instance.

The query requires an index. …

Firestore needs a composite index for this combination of filters and sort. Open the link, create the index, and run the filter again once the index has built.

Index not defined, add ".indexOn": "…", for path "…", to the rules

The Realtime Database orders by a child field only with an index. Add the rule the message names in the Firebase console, under Realtime Database, Rules.

The document changed after it was opened. Reopen it and edit again.

Another writer saved the document between Edit Document opening it and your save. Open it again and redo the change.

The node changed after it was opened. Reopen it and edit again.

The Realtime Database node was written after Edit Document read it. Open it again and redo the change.

Related