2

I have create document like this in react native, I am using rnfirebase library

 firestore()
        .collection('WaterCanData')
        .doc(EntryDate)
        .collection('Entries')
        .doc(values.customerName)
        .set({
            CustomerName: values.customerName,
            CansOut: values.cansOut,
            JarsOut: values.jarsOut,
            EmptyCansIn: values.emptyCansIn,
            JarsIn: values.jarsIn,
            Bottles: values.bottles,
            Ice: values.ice
        })
        .then(() => {
            console.log('Entry added!!!!!!!!!');
        })

When I try to retrieve EntryDate from WaterCanData Coellection I am not able to fetch it(Document name appears in italic font), So how should I retrive this document which contains a subcollection, Below I have attached my ss of data structure Data structure Data structuree

Aariana
  • 39
  • 6

2 Answers2

3

The reason your document appears in italics is because it doesn't currently exist. In Cloud Firestore, subcollections can exist without requiring their parent document to also exist.

Non-existant documents will not appear in queries or snapshots in the client SDKs as stated in the Firebase Console.

This document does not exist, it will not appear in queries or snapshots

If you want to be able to get your entry dates, you need to create the document (which can be empty).

firebase.firestore()
  .collection('WaterCanData')
  .doc(EntryDate)
  .set({}); // an empty document

To create the document at the same time as an entry on it's subcollection, you can use a batched write like so:

const db = firebase.firestore();
const batch = db.batch();

// get references to the relevant locations
const entryDateRef = db
  .collection('WaterCanData')
  .doc(EntryDate);
const customerRef = entryDateRef
  .collection('Entries')
  .doc(values.customerName);

// queue the data to write
batch.set(entryDateRef, {});
batch.set(customerRef, {
  CustomerName: values.customerName,
  CansOut: values.cansOut,
  JarsOut: values.jarsOut,
  EmptyCansIn: values.emptyCansIn,
  JarsIn: values.jarsIn,
  Bottles: values.bottles,
  Ice: values.ice
})

// make changes to database
batch.commit()
  .then(() => {
    console.log('Entry added!!!!!!!!!');
  });

This will then allow you to list all of the entry dates in your database using something like:

firebase.firestore().collection('WaterCanData')
  .get()
  .then((querySnapshot) => {
    querySnapshot.forEach(doc => {
      const entryDate = doc.id;
      // const customerEntriesRef = doc.ref.collection('Entries');

      console.log('Entry date found: ' + entryDate);
    }
  });

If (as an example) you wanted to also find how many entries were linked to a given date, you would need to also query each subcollection (here the code gets a little more confusing).

firebase.firestore().collection('WaterCanData')
  .get()
  .then((querySnapshot) => {
    const fetchSizePromises = [];

    // for each entry date, get the size of it's "Entries" subcollection
    querySnapshot.forEach(doc => {
      const entryDate = doc.id;
      const customerEntriesRef = doc.ref.collection('Entries');
      
      // if this get() fails, just store the error rather than throw it.
      const thisEntrySizePromise = customerEntriesRef.get()
        .then(
          (entriesQuerySnapshot) => {
            return { date: entryDate, size: entriesQuerySnapshot.size }
          },
          (error) => {
            return { date: entryDate, size: -1, error }
          }
        );

      // add this promise to the queue
      fetchSizePromises.push(thisEntrySizePromise)
    }

    // wait for all fetch operations and return their results
    return Promise.all(fetchSizePromises);
  })
  .then((entryInfoResults) => {
    // for each entry, log the result
    entryInfoResults.forEach((entryInfo) => {
      if (entryInfo.error) {
        // this entry failed
        console.log(`${entryInfo.date} has an unknown number of customers in its Entries subcollection due to an error`, entryInfo.error);
      } else {
        // got size successfully
        console.log(`${entryInfo.date} has ${entryInfo.size} customers in its Entries subcollection`);
      }      
    }
  });
samthecodingman
  • 23,122
  • 4
  • 30
  • 54
  • the first code getting regarding listing the dates does not return any data – Aariana Apr 10 '21 at 15:16
  • I will try that thanx, also I have a question is my data model correct, what are good practice to structure data as in my case as I am new to firestore. – Aariana Apr 10 '21 at 15:50
0

Using below code you can console every document id inside waterCanData collection. In your database you have only one document, then it will console your document id. (10042021)

firestore()
    .collection('WaterCanData')
    .get()
    .then((querySnapshot) => {
     querySnapshot.forEach((doc) => {
     console.log(doc.id)
     });
     })
  • As explained by samthecodingman, this will not work because there isn't any "genuine" doc under the `WaterCanData`collection. – Renaud Tarnec Apr 10 '21 at 16:18