From c97ba1151e778b9dbc4c4a221fce58b0f4ba5ac7 Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Sat, 12 Aug 2023 15:03:31 +1200 Subject: [PATCH] Optimize GraphsList Instead of getting a list of max weights, then looping in JS to run SQL queries for max reps, use a subquery. --- GraphsList.tsx | 124 ++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/GraphsList.tsx b/GraphsList.tsx index 873231d..79d9bc0 100644 --- a/GraphsList.tsx +++ b/GraphsList.tsx @@ -2,75 +2,68 @@ import { NavigationProp, useFocusEffect, useNavigation, -} from '@react-navigation/native' -import { useCallback, useState } from 'react' -import { FlatList, Image } from 'react-native' -import { List } from 'react-native-paper' -import { GraphsPageParams } from './GraphsPage' -import { setRepo, settingsRepo } from './db' -import DrawerHeader from './DrawerHeader' -import GymSet from './gym-set' -import Page from './Page' -import Settings from './settings' +} from "@react-navigation/native"; +import { useCallback, useState } from "react"; +import { FlatList, Image } from "react-native"; +import { List } from "react-native-paper"; +import { GraphsPageParams } from "./GraphsPage"; +import { setRepo, settingsRepo } from "./db"; +import DrawerHeader from "./DrawerHeader"; +import GymSet from "./gym-set"; +import Page from "./Page"; +import Settings from "./settings"; export default function GraphsList() { - const [bests, setBests] = useState() - const [term, setTerm] = useState('') - const navigation = useNavigation>() - const [settings, setSettings] = useState() + const [bests, setBests] = useState(); + const [term, setTerm] = useState(""); + const navigation = useNavigation>(); + const [settings, setSettings] = useState(); useFocusEffect( useCallback(() => { - settingsRepo.findOne({ where: {} }).then(setSettings) - }, []), - ) + settingsRepo.findOne({ where: {} }).then(setSettings); + }, []) + ); const refresh = useCallback(async (value: string) => { - const weights = await setRepo - .createQueryBuilder() - .select() - .addSelect('MAX(weight)', 'weight') - .where('name LIKE :name', { name: `%${value.trim()}%` }) - .andWhere('NOT hidden') - .groupBy('name') - .getMany() - console.log(`${GraphsList.name}.refresh:`, { length: weights.length }) - let newBest: GymSet[] = [] - for (const set of weights) { - const reps = await setRepo - .createQueryBuilder() - .select() - .addSelect('MAX(reps)', 'reps') - .where('name = :name', { name: set.name }) - .andWhere('weight = :weight', { weight: set.weight }) - .andWhere('NOT hidden') - .groupBy('name') - .getMany() - newBest.push(...reps) - } - setBests(newBest) - }, []) + const result = await setRepo + .createQueryBuilder("gym_set") + .select(["gym_set.name", "gym_set.reps", "gym_set.weight"]) + .groupBy("gym_set.name") + .innerJoin( + (qb) => + qb + .select(["gym_set2.name", "MAX(gym_set2.weight) AS max_weight"]) + .from(GymSet, "gym_set2") + .where("gym_set2.name LIKE (:name)", { name: `%${value.trim()}%` }) + .groupBy("gym_set2.name"), + "subquery", + "gym_set.name = subquery.gym_set2_name AND gym_set.weight = subquery.max_weight" + ) + .getMany(); + setBests(result); + }, []); useFocusEffect( useCallback(() => { - refresh(term) - }, [refresh, term]), - ) + refresh(term); + }, [refresh, term]) + ); const search = useCallback( (value: string) => { - setTerm(value) - refresh(value) + setTerm(value); + refresh(value); }, - [refresh], - ) + [refresh] + ); const renderItem = ({ item }: { item: GymSet }) => ( navigation.navigate('ViewGraph', { best: item })} + description={`${item.reps} x ${item.weight}${item.unit || "kg"}`} + onPress={() => navigation.navigate("ViewGraph", { best: item })} left={() => (settings.images && item.image && ( )) || - null} + null + } /> - ) + ); return ( <> - + - {bests?.length === 0 - ? ( - - ) - : ( - - )} + {bests?.length === 0 ? ( + + ) : ( + + )} - ) + ); }