Reputation: 19
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
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
:
appointments
(sub-collection):
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