BeginnerInIT
BeginnerInIT

Reputation: 19

Firebase modular trying to use query in nested collections

I'm trying to get data from a nested collection. When I create an appointment - I'm saving the appointmentId and doctorId in the current user. When I need them I take them from the user. And there is the big question - I creating appointments in firestore like this - appointments - [doctorId] (1) - currentDoctorApp - appointmentId - data part1 | part2. I know I can add data like normal - appointments - autoId - data, but I want to separate them, for a better search I think?

(1) - because I think if I have 50 doctors and the current user has appointmenthours at only 2, I will search in these 2 fields, not in all 50

This is the way I add it to appointments collection, but how can I get it? Еspecially when I get more than 1 doctorId. First I have to query by document id. I hope it's not very confusing

try {
        await setDoc(doc(db, `appointments/${params.doctorId}`, 'currentDoctorApp', generatedId), {
            doctorId: params.doctorId,
            userId: currentUser.uid,
            date: date,
            hour: hour,
            status: 'active',
            address: doctorData.hospitalAddres,
            hospital: doctorData.hospitalName
        });

        await updateDoc(doc(db, 'users', currentUser.uid), {
            appointments: arrayUnion({
                appointmentId: generatedId,
                doctorId: params.doctorId,
            })
        });
    } catch (error) {
        console.log(error);
    }

Upvotes: 1

Views: 523

Answers (1)

Marc Anthony B
Marc Anthony B

Reputation: 4109

I would suggest changing your Firestore Data Structure to this:

doctors (collection)
 - documents (auto-id)
   fields (your-fields):
   - name
   - type

users (collection)
 - document (auto-id)
   - appointments (sub-collection)
     - documents (auto-id)
       fields:
       - address
       - date
       - doctorId
       - hospital
       - hour
       - status

If you use the above structure you can remove/delete your existing appointments collection and just refer to the user's sub-collection to avoid redundancy. Here's a screenshots of Firestore Structure from above:

users: enter image description here appointments (sub-collection): enter image description here

doctors: enter image description here

To get all appointments from the users, you can query like this:

const doctors = collection(db, 'doctors');
const q = query(doctors, where("type", "==", "Psychiatrists"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  getUsersAppointment(doc.id);
});

async function getUsersAppointment(doctorId) {
  const appointments = query(collectionGroup(db, 'appointments'), where("doctorId", "==", doctorId), where("status", "==", "active"));
  const querySnapshot = await getDocs(appointments);
  querySnapshot.forEach((doc) => {
      console.log(doc.id, ' => ', doc.data());
  });
}

By using collectionGroup, you would be able to query its sub-collection but you need to configure the indexing first by following the prompt on the first run. The prompt should look like this:

[FirebaseError: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/project-id/firestore/indexes?create_composite=ClZwcm9qZWN0cy90aXBoLW1hcmNhbnRob255Yi9kYXRhYmFzZXMvKGRlZmF1bHQpL2NvbGxlY3Rpb25Hcm91cHMvYXBwb2ludG1lbnRzL2luZGV4ZXMvXxACGgwKCGRvY3RvcklkEAEaCgoGc3RhdHVzEAEaDAoIX19uYW1lX18QAQ] 

Create the index and wait for it to be enabled. The code above would result to:

9smR9t3ZU67CljVIzSbA  =>  {
  hour: '13:00',
  address: 'Test Address',
  doctorId: 'Zx2sWI2KZ3rJbPcUcUKu',
  hospital: 'MedEx',
  date: '2022-03-16',
  status: 'active'
}

You could also do it vice-versa by modifying the above data structure if you want it to call from the doctors and also logically reverse the code by querying the users first.

Upvotes: 1

Related Questions