Simplify tag sql queries

This commit is contained in:
Sam Becker 2024-03-03 15:18:43 -06:00
parent ee008d2861
commit 448c4301de
10 changed files with 39 additions and 54 deletions

View File

@ -1,6 +1,6 @@
import AdminChildPage from '@/components/AdminChildPage';
import { redirect } from 'next/navigation';
import { getPhotosCached, getPhotosTagCountCached } from '@/photo/cache';
import { getPhotosCached } from '@/photo/cache';
import TagForm from '@/tag/TagForm';
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/site/paths';
import PhotoTag from '@/tag/PhotoTag';
@ -8,6 +8,7 @@ import { photoLabelForCount } from '@/photo';
import PhotoLightbox from '@/photo/PhotoLightbox';
import FavsTag from '@/tag/FavsTag';
import { isTagFavs } from '@/tag';
import { getPhotosTagMeta } from '@/services/vercel-postgres';
const MAX_PHOTO_TO_SHOW = 6;
@ -21,10 +22,10 @@ export default async function PhotoPageEdit({
const tag = decodeURIComponent(tagFromParams);
const [
count,
{ count },
photos,
] = await Promise.all([
getPhotosTagCountCached(tag),
getPhotosTagMeta(tag),
getPhotosCached({ tag, limit: MAX_PHOTO_TO_SHOW }),
]);

View File

@ -58,8 +58,7 @@ export default async function PhotoTagPage({
const [
photos,
count,
dateRange,
{ count, dateRange },
] = await getPhotosTagDataCached({ tag });
return <>

View File

@ -19,8 +19,7 @@ export async function generateMetadata({
const [
photos,
count,
dateRange,
{ count, dateRange },
] = await getPhotosTagDataCached({
tag,
limit: GRID_THUMBNAILS_TO_SHOW_MAX,

View File

@ -10,14 +10,14 @@ import { useFormState } from 'react-dom';
import { areSimpleObjectsEqual } from '@/utility/object';
import IconGrSync from '@/site/IconGrSync';
import { getExifDataAction } from './actions';
import { Tags } from '@/tag';
import { TagsWithMeta } from '@/tag';
export default function PhotoEditPageClient({
photo,
uniqueTags,
}: {
photo: Photo
uniqueTags?: Tags
uniqueTags?: TagsWithMeta
}) {
const seedExifData = { url: photo.url };

View File

@ -5,7 +5,7 @@ import PhotoTag from '@/tag/PhotoTag';
import { FaTag } from 'react-icons/fa';
import { IoMdCamera } from 'react-icons/io';
import { PhotoDateRange, dateRangeForPhotos, photoQuantityText } from '.';
import { TAG_FAVS, Tags } from '@/tag';
import { TAG_FAVS, TagsWithMeta } from '@/tag';
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon';
import { FilmSimulations, sortFilmSimulationsWithCount } from '@/simulation';
@ -18,7 +18,7 @@ export default function PhotoGridSidebar({
photosCount,
photosDateRange,
}: {
tags: Tags
tags: TagsWithMeta
cameras: Cameras
simulations: FilmSimulations
photosCount: number

View File

@ -11,10 +11,9 @@ import {
getPhotosCount,
getPhotosCameraCount,
getPhotosCountIncludingHidden,
getPhotosTagCount,
getUniqueCameras,
getUniqueTags,
getPhotosTagDateRange,
getPhotosTagMeta,
getPhotosCameraDateRange,
getUniqueTagsHidden,
getUniqueFilmSimulations,
@ -162,12 +161,6 @@ export const getPhotosCountIncludingHiddenCached =
[KEY_PHOTOS, KEY_COUNT, KEY_HIDDEN],
);
export const getPhotosTagCountCached =
unstable_cache(
getPhotosTagCount,
[KEY_PHOTOS, KEY_TAGS],
);
export const getPhotosCameraCountCached = (
...args: Parameters<typeof getPhotosCameraCount>
) =>
@ -182,9 +175,9 @@ export const getPhotosFilmSimulationCountCached =
[KEY_PHOTOS, KEY_FILM_SIMULATIONS, KEY_COUNT],
);
export const getPhotosTagDateRangeCached =
export const getPhotosTagMetaCached =
unstable_cache(
getPhotosTagDateRange,
getPhotosTagMeta,
[KEY_PHOTOS, KEY_TAGS, KEY_DATE_RANGE],
);

View File

@ -23,7 +23,7 @@ import { toastSuccess, toastWarning } from '@/toast';
import { getDimensionsFromSize } from '@/utility/size';
import ImageBlurFallback from '@/components/ImageBlurFallback';
import { BLUR_ENABLED } from '@/site/config';
import { Tags, sortTagsObjectWithoutFavs } from '@/tag';
import { TagsWithMeta, sortTagsObjectWithoutFavs } from '@/tag';
import { formatCount, formatCountDescriptive } from '@/utility/string';
const THUMBNAIL_SIZE = 300;
@ -38,7 +38,7 @@ export default function PhotoForm({
initialPhotoForm: Partial<PhotoFormData>
updatedExifData?: Partial<PhotoFormData>
type?: 'create' | 'edit'
uniqueTags?: Tags
uniqueTags?: TagsWithMeta
debugBlur?: boolean
}) {
const [formData, setFormData] =

View File

@ -9,7 +9,7 @@ import {
} from '@/photo';
import { Camera, Cameras, createCameraKey } from '@/camera';
import { parameterize } from '@/utility/string';
import { Tags } from '@/tag';
import { TagsWithMeta } from '@/tag';
import { FilmSimulation, FilmSimulations } from '@/simulation';
import { PRIORITY_ORDER_ENABLED } from '@/site/config';
import { screenForPPR } from '@/utility/ppr';
@ -165,12 +165,6 @@ const sqlGetPhotosCountIncludingHidden = async () => sql`
SELECT COUNT(*) FROM photos
`.then(({ rows }) => parseInt(rows[0].count, 10));
const sqlGetPhotosTagCount = async (tag: string) => sql`
SELECT COUNT(*) FROM photos
WHERE ${tag}=ANY(tags) AND
hidden IS NOT TRUE
`.then(({ rows }) => parseInt(rows[0].count, 10));
const sqlGetPhotosCameraCount = async (camera: Camera) => sql`
SELECT COUNT(*) FROM photos
WHERE
@ -195,14 +189,17 @@ const sqlGetPhotosDateRange = async () => sql`
? rows[0] as PhotoDateRange
: undefined);
const sqlGetPhotosTagDateRange = async (tag: string) => sql`
SELECT MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
const sqlGetPhotosTagMeta = async (tag: string) => sql`
SELECT COUNT(*), MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
FROM photos
WHERE ${tag}=ANY(tags) AND
hidden IS NOT TRUE
`.then(({ rows }) => rows[0]?.start && rows[0]?.end
? rows[0] as PhotoDateRange
: undefined);
`.then(({ rows }) => ({
count: parseInt(rows[0].count, 10),
...rows[0]?.start && rows[0]?.end
? { dateRange: rows[0] as PhotoDateRange }
: undefined,
}));
const sqlGetPhotosCameraDateRange = async (camera: Camera) => sql`
SELECT MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
@ -232,7 +229,7 @@ const sqlGetUniqueTags = async () => sql`
WHERE hidden IS NOT TRUE
GROUP BY tag
ORDER BY tag ASC
`.then(({ rows }): Tags => rows.map(({ tag, count }) => ({
`.then(({ rows }): TagsWithMeta => rows.map(({ tag, count }) => ({
tag: tag as string,
count: parseInt(count, 10),
})));
@ -242,7 +239,7 @@ const sqlGetUniqueTagsHidden = async () => sql`
FROM photos
GROUP BY tag
ORDER BY tag ASC
`.then(({ rows }): Tags => rows.map(({ tag, count }) => ({
`.then(({ rows }): TagsWithMeta => rows.map(({ tag, count }) => ({
tag: tag as string,
count: parseInt(count, 10),
})));
@ -461,15 +458,10 @@ export const getUniqueTags = () =>
safelyQueryPhotos(sqlGetUniqueTags, 'getUniqueTags');
export const getUniqueTagsHidden = () =>
safelyQueryPhotos(sqlGetUniqueTagsHidden, 'getUniqueTagsHidden');
export const getPhotosTagDateRange = (tag: string) =>
export const getPhotosTagMeta = (tag: string) =>
safelyQueryPhotos(
() => sqlGetPhotosTagDateRange(tag),
'getPhotosTagDateRange',
);
export const getPhotosTagCount = (tag: string) =>
safelyQueryPhotos(
() => sqlGetPhotosTagCount(tag),
'getPhotosTagCount',
() => sqlGetPhotosTagMeta(tag),
'getPhotosTagMeta',
);
// CAMERAS

View File

@ -1,7 +1,6 @@
import {
getPhotosCached,
getPhotosTagCountCached,
getPhotosTagDateRangeCached,
getPhotosTagMetaCached,
} from '@/photo/cache';
import {
PaginationSearchParams,
@ -18,8 +17,7 @@ export const getPhotosTagDataCached = ({
}) =>
Promise.all([
getPhotosCached({ tag, limit }),
getPhotosTagCountCached(tag),
getPhotosTagDateRangeCached(tag),
getPhotosTagMetaCached(tag),
]);
export const getPhotosTagDataCachedWithPagination = async ({
@ -33,7 +31,7 @@ export const getPhotosTagDataCachedWithPagination = async ({
}) => {
const { offset, limit } = getPaginationFromSearchParams(searchParams);
const [photos, count, dateRange] =
const [photos, { count, dateRange }] =
await getPhotosTagDataCached({
tag,
limit: limitProp ?? limit,

View File

@ -13,10 +13,13 @@ import { capitalizeWords, convertStringToArray } from '@/utility/string';
export const TAG_FAVS = 'favs';
export type Tags = {
export type TagWithMeta = {
tag: string
count: number
}[]
dataRange?: PhotoDateRange
}
export type TagsWithMeta = Omit<TagWithMeta, 'dateRange'>[]
export const formatTag = (tag?: string) =>
capitalizeWords(tag?.replaceAll('-', ' '));
@ -41,7 +44,7 @@ export const sortTags = (
.sort((a, b) => isTagFavs(a) ? -1 : a.localeCompare(b));
export const sortTagsObject = (
tags: Tags,
tags: TagsWithMeta,
tagToHide?: string,
) => tags
.filter(({ tag }) => tag!== tagToHide)
@ -50,7 +53,7 @@ export const sortTagsObject = (
export const sortTagsWithoutFavs = (tags: string[]) =>
sortTags(tags, TAG_FAVS);
export const sortTagsObjectWithoutFavs = (tags: Tags) =>
export const sortTagsObjectWithoutFavs = (tags: TagsWithMeta) =>
sortTagsObject(tags, TAG_FAVS);
export const descriptionForTaggedPhotos = (