114

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?

André Kool
  • 4,668
  • 12
  • 33
  • 43
Developer
  • 1,643
  • 2
  • 14
  • 25
  • Try: `const docRef = doc(db, collection_name, doc_id);` and then `wanted_doc = await getDoc(docRef); ` – hoomi Apr 03 '22 at 20:06

9 Answers9

273

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.

Denys Mikhalenko
  • 3,476
  • 2
  • 13
  • 17
114

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

Todd Kerpelman
  • 15,719
  • 3
  • 39
  • 40
  • 4
    Hey do you know how to get document ID that obeys some condition mentioned in a query in firestore – Divya Galla Jan 02 '18 at 08:47
  • 55
    What to do if we need multiple where case (multiple id)? – Midhilaj May 19 '19 at 11:13
  • 9
    In python I get `AttributeError: 'CollectionReference' object has no attribute 'doc'`. Turns out the syntax there is `db.collection('books').document('longid').get()` – szeitlin Jun 27 '19 at 00:01
  • @Midhilaj : could it be that document id's are unique? – gusgonnet Aug 14 '20 at 01:49
  • 1
    @Midhilaj in my case i have another collection where i have document of each user which store the data that satisfy a specific condition. i have very limited conditions e.g what book is uploaded by which user. – Abdul Wahid Mar 14 '21 at 09:32
50

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

Jürgen Brandstetter
  • 6,226
  • 3
  • 33
  • 30
  • This is handy when using the Firestore UI in prod or in the emulator, where you can't use something like `db.collection('foo').doc('xxxx')` – John Gordon Jul 10 '20 at 18:09
  • 1
    This is what I needed on my cloud function implementation, client sends the doc ids and I need to query all docs with "in" and get docs – Divyanshu Negi Oct 16 '20 at 08:18
  • Thanks mate, that´s the information I was looking for! – codingbuddha Nov 29 '20 at 15:55
  • @DivyanshuNegi The admin SDK has a `getAll()` function https://googleapis.dev/nodejs/firestore/latest/Firestore.html#getAll I think this what you are looking for. Right? – Jürgen Brandstetter Dec 02 '20 at 09:33
  • @JohnGordon Unfortunately the Firebase Web UI doesn't let me create a query with `__name__`. The apply button is just greyed out :( – Sven Jacobs Sep 15 '21 at 10:10
  • Thanks for the example, I would have never realized it could be used that way from the documentation, tried it with the php sdk and it works. – Alex Sep 28 '21 at 17:22
25

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")
Mulan
  • 119,326
  • 28
  • 214
  • 246
13

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) => { })
j3ff
  • 5,139
  • 7
  • 39
  • 50
Venkat
  • 327
  • 3
  • 13
7

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'))
Syed Basim
  • 96
  • 1
  • 2
1

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);
});
John
  • 84
  • 10
1

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];
};
MickyTonji
  • 11
  • 2
0

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();
}
Mejan
  • 668
  • 10
  • 16