Click here to Skip to main content
16,020,186 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a fitness dashboard to show activity of users. However the way the database is structured has made this difficult.{collection/document/subcollection/document}

Currently the dashboard does show each user and all the information (i.e. calories) for the previous workout they logged. However some users can do multiple workouts in a set amount of time i.e. 12 hours and there workout and workout information is stored in a subcollection. What i would like to do is for those users who have a subcollection in there document, i would like to query (by set amount of time ) and read all the data in the sub collection for that particular user and add it together (total calories) and show it in the dashboard.

I am having issues doing this because i can retrieving the data and invoking the data. However no errors.

ps. this is for development, actual database is much larger

App.js

JavaScript
function App() {
    const [user, setUser] = useState(null);
    const [workouts, setworkouts] = useState([]);
    const [error, setError] = useState(null);

    useEffect(() => {
        const unsubscribe = firebase
            .auth()
            .onAuthStateChanged((user) => setUser(user));
        return unsubscribe;
    }, []);

    useEffect(() => {
        const unsubscribe = FirestoreService.getworkoutItems(
            (qSnapshot) => {
                const updatedworkouts = qSnapshot.docs.map((doc) => ({
                    id: doc.id,
                    ...doc.data(),
                }));
                setworkouts(updatedworkouts);
                setError(false);
            },
            (error) => setError(true)
        );
        return unsubscribe;
    });

    useEffect(() => {
        const fetchData = async () => {
            try {
                const qSnapshot = await getDocs(collection(db, "workouts"));

                let allDocs = [];
                qSnapshot.forEach((doc) => {
                    allDocs.push({ id: doc.id, ...doc.data() });
                });
                for (const item of allDocs) {
                    const time = 12;
                    const timeDiff = moment(new Date()).subtract(time, "hours")._d;
                    const qSnap = await getDocs(
                        collection(db, `workouts/${item.id}/Extra`).where(
                            "time",
                            ">=",
                            timeDiff
                        )
                    );

                    let totalCount = 0;
                    totalCount += qSnap.calories;
                    console.log(qSnap);
                    console.log(totalCount);
                    let allQDocs = [];

                    if (!qSnap.empty) {
                        qSnap.forEach((doc) => {
                            allQDocs.push({
                                id: doc.id,
                                calories: doc.data().calories,
                                ...doc.data(),
                            });
                            console.log(allQDocs);
                            console.log(allQDocs[0].calories);
                        });
                    } else {
                    }
                }
            } catch (err) {
                console.log(err);
            }
        };
        fetchData();
    }, []);

    return (
        <div>
            <Container>
                <Header />
                <Divider horizontal section>
                    Fitness Monitor
                </Divider>

                {!error && user ? (
                    <Card.Group itemsPerRow="8">
                        {workouts &&
                            workouts.map((workout) => {
                                return <Cards key={workout.id} workout={workout} />;
                            })}
                    </Card.Group>
                ) : (
                    <h2> sign in </h2>
                )}
            </Container>
        </div>
    );
}

export default App;




firebase.js

JavaScript
const firebaseConfig = {
    XXXXXXXXXXXXXXXXX,
};

firebase.initializeApp(firebaseConfig);

const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);

export const auth = firebase.auth();

const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({ prompt: "select_account" });

export const signInWithGoogle = () => auth.signInWithPopup(provider);

export const getworkoutItems = (snapshot, error) => {
    const ref = collection(db, "workouts");
    const query = query(ref);
    return onSnapshot(query, snapshot, error);
};



[![Structure of database for one workout user][1]][1]

[![Structure of database for a user who has a subcollection of workouts][2]][2]

Structure of database for one workout user

[1]: https://i.stack.imgur.com/1AKy9.png

Structure of database for a user who has a subcollection of workouts

[2]: https://i.stack.imgur.com/62giC.png

What I have tried:

Have tried using type literals
Posted
Updated 14-Jul-22 7:04am
v2

1 solution

Bad design leads to bad code. There is no logical reason to create a "subcollection" simply because someone works out more than once in a day.

You have a workout for a give date and time by person x. You want to total by day, week, etc. it's simply a matter of grouping by person, date, etc.

Your current design requires you to "promote" your subcollection through various gyrations.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900