fix: add column to posts table that is a string of content to use search index on

This commit is contained in:
Stevan Freeborn
2023-09-16 10:53:28 -05:00
parent 18cb4fe0d9
commit e2161e62c3
6 changed files with 53 additions and 21 deletions
+21 -6
View File
@@ -28,8 +28,10 @@ export const createOrUpdatePost = mutation({
return 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER'; return 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER';
} }
const contentText = args.content.join('\n');
if (args.id) { if (args.id) {
await ctx.db.patch(args.id, { content: args.content }); await ctx.db.patch(args.id, { content: args.content, contentText });
return; return;
} }
@@ -37,6 +39,7 @@ export const createOrUpdatePost = mutation({
userId: user._id, userId: user._id,
content: args.content, content: args.content,
parentPostId: args.parentPostId, parentPostId: args.parentPostId,
contentText,
}); });
}, },
}); });
@@ -44,12 +47,16 @@ export const createOrUpdatePost = mutation({
export const getUsersPostById = query({ export const getUsersPostById = query({
args: { userId: v.id('users'), paginationOpts: paginationOptsValidator }, args: { userId: v.id('users'), paginationOpts: paginationOptsValidator },
handler: async (ctx, args) => { handler: async (ctx, args) => {
return await ctx.db const posts = await ctx.db
.query('posts') .query('posts')
.withIndex('by_user_id', q => q.eq('userId', args.userId)) .withIndex('by_user_id', q => q.eq('userId', args.userId))
.filter(q => q.eq(q.field('parentPostId'), undefined)) .filter(q => q.eq(q.field('parentPostId'), undefined))
.order('desc') .order('desc')
.paginate(args.paginationOpts); .paginate(args.paginationOpts);
const postDtos = posts.page.map(createPostDto);
return { ...posts, page: postDtos };
}, },
}); });
@@ -81,7 +88,7 @@ export const getPostById = query({
} }
return { return {
...post, ...createPostDto(post),
user: createUserDto(user), user: createUserDto(user),
}; };
}, },
@@ -100,6 +107,7 @@ export const getRepliesByParentId = query({
ctx, ctx,
posts: replies.page, posts: replies.page,
}); });
return { ...replies, page: repliesWithUserData }; return { ...replies, page: repliesWithUserData };
}, },
}); });
@@ -191,8 +199,9 @@ export const getPostsBySearchTerm = query({
const posts = await ctx.db const posts = await ctx.db
.query('posts') .query('posts')
.withSearchIndex('search_by_content', q => .withSearchIndex('search_by_content', q =>
q.search('content', args.term).eq('parentPostId', undefined) q.search('contentText', args.term)
) )
.filter(q => q.eq(q.field('parentPostId'), undefined))
.paginate(args.paginationOpts); .paginate(args.paginationOpts);
const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page }); const postsWithUser = await getPostsWithUsers({ ctx, posts: posts.page });
@@ -210,19 +219,25 @@ async function getPostsWithUsers({
}) { }) {
return await Promise.all( return await Promise.all(
posts.map(async post => { posts.map(async post => {
const postDto = createPostDto(post);
const user = await ctx.db.get(post.userId); const user = await ctx.db.get(post.userId);
if (user === null) { if (user === null) {
return { return {
...post, ...postDto,
user: createUserDto(user), user: createUserDto(user),
}; };
} }
return { return {
...post, ...postDto,
user: createUserDto(user), user: createUserDto(user),
}; };
}) })
); );
} }
function createPostDto(post: Doc<'posts'>) {
const { contentText, ...postDto } = post;
return postDto;
}
+2 -1
View File
@@ -44,11 +44,12 @@ export default defineSchema(
parentPostId: v.optional(v.id('posts')), parentPostId: v.optional(v.id('posts')),
userId: v.id('users'), userId: v.id('users'),
content: v.array(v.string()), content: v.array(v.string()),
contentText: v.string(),
}) })
.index('by_user_id', ['userId']) .index('by_user_id', ['userId'])
.index('by_parent_id', ['parentPostId']) .index('by_parent_id', ['parentPostId'])
.searchIndex('search_by_content', { .searchIndex('search_by_content', {
searchField: 'content', searchField: 'contentText',
filterFields: ['parentPostId'], filterFields: ['parentPostId'],
}), }),
likes: defineTable({ likes: defineTable({
-12
View File
@@ -1,12 +0,0 @@
import SearchResults from '@/components/SearchResults';
export default function SearchPage({ params }: { params: { term: string } }) {
return (
<main className='flex flex-col items-center flex-1'>
<div className='flex flex-col w-full max-w-4xl gap-4'>
<h1 className='text-4xl font-bold'>Here&apos;s what we found</h1>
<SearchResults term={params.term} />
</div>
</main>
);
}
+26
View File
@@ -0,0 +1,26 @@
import SearchResults from '@/components/SearchResults';
export default function SearchPage({
searchParams,
}: {
searchParams: { [key: string]: string | string[] | undefined };
}) {
let term = searchParams.term;
if (term === undefined) {
term = '';
}
if (Array.isArray(term)) {
term = term.length > 0 ? term[0] : '';
}
return (
<main className='flex flex-col items-center flex-1'>
<div className='flex flex-col w-full max-w-4xl gap-4'>
<h1 className='text-4xl font-bold'>Here&apos;s what we found</h1>
<SearchResults term={term} />
</div>
</main>
);
}
+3 -1
View File
@@ -8,4 +8,6 @@ export type UserDto = {
clerkUserId: string; clerkUserId: string;
}; };
export type PostWithUserDto = Doc<'posts'> & { user: UserDto }; export type PostWithUserDto = Omit<Doc<'posts'>, 'contentText'> & {
user: UserDto;
};
+1 -1
View File
@@ -63,7 +63,7 @@ export default function Navbar() {
<form <form
onSubmit={e => { onSubmit={e => {
e.preventDefault(); e.preventDefault();
router.push(`/search/${term}`); router.push(`/search?term=${term}`);
}} }}
className='flex w-full relative' className='flex w-full relative'
> >