Query firestore database for document id

Posted on

Query firestore database for document id – Even if we have a good project plan and a logical concept, we will spend the majority of our time correcting errors abaout and javascript. Furthermore, our application can run without obvious errors with JavaScript, we must use various ways to ensure that everything is operating properly. In general, there are two types of errors that you’ll encounter while doing something wrong in code: Syntax Errors and Logic Errors. To make bug fixing easier, every JavaScript error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the JavaScript error, look at the discuss below to fix problem about Query firestore database for document id.

Problem :

I want to query a firestore database for document id. Currently I have the following code:

db.collection('books').where('id', '==', 'fK3ddutEpD2qQqRMXNW5').get()

I don’t get a result. But when I query for a different field it works:

db.collection('books').where('genre', '==', 'biography').get()

How is the name of the document id called?

Solution :

I am a bit late, but there is actually a way to do this

db.collection('books').where(firebase.firestore.FieldPath.documentId(), '==', 'fK3ddutEpD2qQqRMXNW5').get()

This might be useful when you’re dealing with firebase security rules and only want to query for the records you’re allowed to access.

Try this:

db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get()

(The first query is looking for an explicit user-set field called ‘id’, which probably isn’t what you want.)

You can use the __name__ key word to use your document ID in a query.

Instead of this db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get() you can write

db.collection('books').where('__name__', '==' ,'fK3ddutEpD2qQqRMXNW5').get().

In this case you should get an array of length 1 back.

The firebase docs mention this feature in the rules documentation. https://firebase.google.com/docs/reference/rules/rules.firestore.Resource

June, 2021

The new v9 modular sdk is tree-shakeable and results in smaller compiled apps. It is recommended for all new Firestore apps.

import { doc, getDoc } from "firebase/firestore";

const snap = await getDoc(doc(db, 'books', 'fK3ddutEpD2qQqRMXNW5'))

if (snap.exists()) {
  console.log(snap.data())
}
else {
  console.log("No such document")
}

This is based on the example from the firestore docs

import { doc, getDoc } from "firebase/firestore";

const docRef = doc(db, "cities", "SF");
const docSnap = await getDoc(docRef);

if (docSnap.exists()) {
  console.log("Document data:", docSnap.data());
}
else {
  // doc.data() will be undefined in this case
  console.log("No such document!");
}

You could make this into a helper function

async function getDocument (coll, id) {
  const snap = await getDoc(doc(db, coll, id))
  if (snap.exists())
    return snap.data()
  else
    return Promise.reject(Error(`No such document: ${coll}.${id}`))
}

getDocument("books", "fK3ddutEpD2qQqRMXNW5")

You can get a document by its id following this pattern:

firebase
  .firestore()
  .collection("Your collection")
  .doc("documentId")
  .get()
  .then((docRef) => { console.log(docRef.data()) })
  .catch((error) => { })

While everyone is telling to use .get(), which is totally reasonable but it’s not always the case.

Maybe you want to filter data based on id (using a where query for example).

This is how you do it in Firebase v9 modular SDK:

import {collection, documentId} from 'firebase/firestore'

const booksRef = collection('books')

const q = query(booksRef, where(documentId(), '==', 'fK3ddutEpD2qQqRMXNW5'))

From Firestore docs for Get a document.

var docRef = db.collection("cities").doc("SF");

docRef.get().then(function(doc) {
    if (doc.exists) {
        console.log("Document data:", doc.data());
    } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});

If you are looking for more dynamic queries with a helper function, you can simply try this.

import { db} from '@lib/firebase';

import {query, collection, getDocs ,documentId } from "firebase/firestore";

const getResult = async (_value) => {
     const _docId = documented()
     const _query = [{
        field: _docID,
        operator: '==',
        value: _value
      }]
// calling function
    const result = await getDocumentsByQuery("collectionName", qColl)
    console.log("job result: ", result) 
}

// can accept multiple query args
const getDocumentsByQuery = async (collectionName, queries) => {
    const queryArgs = [];
    queries.forEach(q => {
        queryArgs.push(
            where(q.field, q.operator, q.value)
        );
    });

    const _query = query(collection(db, collectionName), ...queryArgs);
    const querySn = await getDocs(_query);
   
   const documents = [];
    querySn.forEach(doc => {
        documents.push({ id: doc.id, ...doc.data() });
    });

    return documents[0];
};

This is the first link that came up when I was looking to solve it in the Golang SDK, so I’ll add my solution in case anyone else is looking for it:

package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/firestore"
    firebase "firebase.google.com/go/v4"
    "google.golang.org/api/option"
)

type (
    Car struct {
        ID    string
        Name  string  `firestore:"name"`
        Make  string  `firestore:"make"`
        Price float64 `firestore:"make"`
    }
)

func main() {
    ctx := context.Background()

    // Use a service account
    options := option.WithCredentialsFile("PATH/TO/SERVICE/FILE.json")

    // Set project id
    conf := &firebase.Config{ProjectID: "PROJECT_NAME"}

    // Initialize app
    app, err := firebase.NewApp(ctx, conf, options)
    if err != nil {
        log.Fatal(err)
    }

    // Get firestore client
    client, err := app.Firestore(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    collectionRef := client.Collection("CAR_COLLECTION")

    // firestore.DocumentID == "__name__" 
    docSnap, err := collectionRef.Where(firestore.DocumentID, "==", collectionRef.Doc("001")).Get(ctx)
    if err != nil {
        log.Fatal(err)
    }

    // Unmarshall item
    car := Car{}
    docSnap.DataTo(&car)
    car.ID = docSnap.Ref.ID

    // Print car list
    fmt.Println(car)
}

Just to clear confusion here

Remember, You should use async/await to fetch data whether fetching full collection or a single doc.

async function someFunction(){
 await db.collection('books').doc('fK3ddutEpD2qQqRMXNW5').get();
}

Leave a Reply

Your email address will not be published. Required fields are marked *