Hmza
Hmza6mo ago

yeahh i might know the problem. lets see

yeahh i might know the problem. lets see your function and probably can fix it right away
26 Replies
Hmza
HmzaOP6mo ago
can you post here
M Zeeshan
M Zeeshan6mo ago
sure
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
let results: PaginationResult<Doc<'skills'>>;

const isPublished = args.is_published;
const isFeatured = args.is_featured;

if (!args.query) {
if (isFeatured !== undefined && isPublished !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('featured_and_published', (q) =>
q
.eq('is_deleted', false)
.eq('is_featured', isFeatured)
.eq('is_published', isPublished),
)
.paginate(args.paginationOpts);
} else if (isPublished !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('published', (q) =>
q.eq('is_deleted', false).eq('is_published', isPublished),
)
.paginate(args.paginationOpts);
} else if (isFeatured !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('featured', (q) =>
q.eq('is_deleted', false).eq('is_featured', isFeatured),
)
.paginate(args.paginationOpts);
} else {
results = await ctx.db
.query('skills')
.withIndex('featured', (q) => q.eq('is_deleted', false))
.paginate(args.paginationOpts);
}
} rest code...
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
let results: PaginationResult<Doc<'skills'>>;

const isPublished = args.is_published;
const isFeatured = args.is_featured;

if (!args.query) {
if (isFeatured !== undefined && isPublished !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('featured_and_published', (q) =>
q
.eq('is_deleted', false)
.eq('is_featured', isFeatured)
.eq('is_published', isPublished),
)
.paginate(args.paginationOpts);
} else if (isPublished !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('published', (q) =>
q.eq('is_deleted', false).eq('is_published', isPublished),
)
.paginate(args.paginationOpts);
} else if (isFeatured !== undefined) {
results = await ctx.db
.query('skills')
.withIndex('featured', (q) =>
q.eq('is_deleted', false).eq('is_featured', isFeatured),
)
.paginate(args.paginationOpts);
} else {
results = await ctx.db
.query('skills')
.withIndex('featured', (q) => q.eq('is_deleted', false))
.paginate(args.paginationOpts);
}
} rest code...
prev code... else {
results = await ctx.db
.query('skills')
.withSearchIndex('search_title', (q) => {
if (
args.is_featured !== undefined &&
args.is_published !== undefined
) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_featured', args.is_featured)
.eq('is_published', args.is_published);
}

if (args.is_featured !== undefined) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_featured', args.is_featured);
}

if (args.is_published !== undefined) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_published', args.is_published!);
}

return q
.search('title', args.query!)
.eq('is_deleted', false);
})
.paginate(args.paginationOpts);
}

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
prev code... else {
results = await ctx.db
.query('skills')
.withSearchIndex('search_title', (q) => {
if (
args.is_featured !== undefined &&
args.is_published !== undefined
) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_featured', args.is_featured)
.eq('is_published', args.is_published);
}

if (args.is_featured !== undefined) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_featured', args.is_featured);
}

if (args.is_published !== undefined) {
return q
.search('title', args.query!)
.eq('is_deleted', false)
.eq('is_published', args.is_published!);
}

return q
.search('title', args.query!)
.eq('is_deleted', false);
})
.paginate(args.paginationOpts);
}

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
Hmza
HmzaOP6mo ago
i'm still looking. but one suggestion right of the top is. you should only build query with your if and else and don't return the paginate after every condition. rather just build queries first and return at the end. something like this
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
let queryBuilder = ctx.db.query('skills').eq('is_deleted', false);

if (args.query) {
queryBuilder = queryBuilder.withSearchIndex('search_title', (q) =>
q.search('title', args.query!)
);
} else {
queryBuilder = queryBuilder.withIndex('featured_and_published');
}

if (args.is_featured !== undefined) {
queryBuilder = queryBuilder.eq('is_featured', args.is_featured);
}

if (args.is_published !== undefined) {
queryBuilder = queryBuilder.eq('is_published', args.is_published);
}

const results = await queryBuilder.paginate(args.paginationOpts);

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
let queryBuilder = ctx.db.query('skills').eq('is_deleted', false);

if (args.query) {
queryBuilder = queryBuilder.withSearchIndex('search_title', (q) =>
q.search('title', args.query!)
);
} else {
queryBuilder = queryBuilder.withIndex('featured_and_published');
}

if (args.is_featured !== undefined) {
queryBuilder = queryBuilder.eq('is_featured', args.is_featured);
}

if (args.is_published !== undefined) {
queryBuilder = queryBuilder.eq('is_published', args.is_published);
}

const results = await queryBuilder.paginate(args.paginationOpts);

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
M Zeeshan
M Zeeshan6mo ago
I tried, but I forgot the error message I received. i can try you suggestion again
Hmza
HmzaOP6mo ago
hmm, i think you should because maybe because you are returning with every condition so its re running the pagination again with filters in your if else and not loading the whole data.
M Zeeshan
M Zeeshan6mo ago
Let me try it now, and I'll provide you with feedback on your suggestion.
Hmza
HmzaOP6mo ago
👍
M Zeeshan
M Zeeshan6mo ago
very basic query and usePaginatedQuery does not merge results
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const results = await ctx.db
.query('skills')
.paginate(args.paginationOpts);

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
export const getMultiple = query({
args: {
query: v.optional(v.string()),
is_published: v.optional(v.boolean()),
is_featured: v.optional(v.boolean()),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const results = await ctx.db
.query('skills')
.paginate(args.paginationOpts);

return {
success: true,
message: 'skills retrieved successfully!',
...results,
};
},
});
Hmza
HmzaOP6mo ago
what does your frontend code looks like ?
M Zeeshan
M Zeeshan6mo ago
const searchParams = useSearchParams();

const query = searchParams.get('query') ?? '';

const is_published = searchParams.get('is_published');
const is_featured = searchParams.get('is_featured');

const [isDeleting, setIsDeleting] = React.useState('');

const { isLoading, results, loadMore, status } = usePaginatedQuery(
api.skills.getMultiple,
{
query,
is_published:
is_published === 'true'
? true
: is_published === 'false'
? false
: undefined,
is_featured:
is_featured === 'true'
? true
: is_featured === 'false'
? false
: undefined,
},
{ initialNumItems: 20 },
);
const searchParams = useSearchParams();

const query = searchParams.get('query') ?? '';

const is_published = searchParams.get('is_published');
const is_featured = searchParams.get('is_featured');

const [isDeleting, setIsDeleting] = React.useState('');

const { isLoading, results, loadMore, status } = usePaginatedQuery(
api.skills.getMultiple,
{
query,
is_published:
is_published === 'true'
? true
: is_published === 'false'
? false
: undefined,
is_featured:
is_featured === 'true'
? true
: is_featured === 'false'
? false
: undefined,
},
{ initialNumItems: 20 },
);
Hmza
HmzaOP6mo ago
can you try without extra params ?
M Zeeshan
M Zeeshan6mo ago
okay
Hmza
HmzaOP6mo ago
also try returning only results here ?
M Zeeshan
M Zeeshan6mo ago
sure same problem
export const getMultiple = query({
args: {
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const results = await ctx.db
.query('skills')
.paginate(args.paginationOpts);

return results;
},
});
export const getMultiple = query({
args: {
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const results = await ctx.db
.query('skills')
.paginate(args.paginationOpts);

return results;
},
});
const { isLoading, results, loadMore, status } = usePaginatedQuery(
api.skills.getMultiple,
{},
{ initialNumItems: 20 },
);
const { isLoading, results, loadMore, status } = usePaginatedQuery(
api.skills.getMultiple,
{},
{ initialNumItems: 20 },
);
Hmza
HmzaOP6mo ago
isLoading in the usePaginatedQuery doesn't give you any error ? ok so you mentioned something about infinite scrolling ? how are you managing that ?
M Zeeshan
M Zeeshan6mo ago
infinite scroll
React.useEffect(() => {
let lastScroll = 0;
let lastScrollDirection = 0; // 1 is down, -1 is up

const observer = new IntersectionObserver(
(entries) => {
if (
entries[0].isIntersecting &&
lastScrollDirection === 1 &&
status === 'CanLoadMore'
) {
loadMore(10);
}
},
{ threshold: 1, rootMargin: '0px 0px 300px 0px' },
);

observer.observe(document.getElementById('bottom')!);

const handleScroll = () => {
const currentScroll = window.scrollY;

const newScrollDirection = currentScroll > lastScroll ? 1 : -1;

lastScroll = currentScroll;
lastScrollDirection = newScrollDirection;
};

window.addEventListener('scroll', handleScroll);

return () => {
window.removeEventListener('scroll', handleScroll);

observer.disconnect();
};
}, [loadMore, status]);
React.useEffect(() => {
let lastScroll = 0;
let lastScrollDirection = 0; // 1 is down, -1 is up

const observer = new IntersectionObserver(
(entries) => {
if (
entries[0].isIntersecting &&
lastScrollDirection === 1 &&
status === 'CanLoadMore'
) {
loadMore(10);
}
},
{ threshold: 1, rootMargin: '0px 0px 300px 0px' },
);

observer.observe(document.getElementById('bottom')!);

const handleScroll = () => {
const currentScroll = window.scrollY;

const newScrollDirection = currentScroll > lastScroll ? 1 : -1;

lastScroll = currentScroll;
lastScrollDirection = newScrollDirection;
};

window.addEventListener('scroll', handleScroll);

return () => {
window.removeEventListener('scroll', handleScroll);

observer.disconnect();
};
}, [loadMore, status]);
Hmza
HmzaOP6mo ago
i'm testing something on my own right now if i'm wrong after all this discussion. i'll be furious 😂 never faced issue with pagination
M Zeeshan
M Zeeshan6mo ago
I'm interested in seeing your results.
Hmza
HmzaOP6mo ago
this should mean it merges the results right?
No description
Hmza
HmzaOP6mo ago
so i'm also using infinite scroll in my code here https://github.com/hamzasaleem2/queryquest/blob/main/src/components/qb.tsx
GitHub
queryquest/src/components/qb.tsx at main · hamzasaleem2/queryquest
Contribute to hamzasaleem2/queryquest development by creating an account on GitHub.
M Zeeshan
M Zeeshan6mo ago
its mean i have bugs....
Hmza
HmzaOP6mo ago
yep. there might be something related to how you are handling scrolling then ? maybe try console logging the results from usePaginatedQuery in useEffect after you loadMore just to see if the results are growing and then you can take reference from the queryquest above to see how infinite scrolling works in there.
M Zeeshan
M Zeeshan6mo ago
sure... yeah it grows....
Hmza
HmzaOP6mo ago
there we go.re do your scrolling probably
M Zeeshan
M Zeeshan6mo ago
Ugh, I'M SO FRUSTRATED WITH MYSELF!!! I just realized its MY OWN MISTAKE!!! Calling loadMore() sets the isLoading state to true.
{
!isLoading ? null : results.map()
}
{
!isLoading ? null : results.map()
}
I owe you one! Thanks for the help!
룬룬이
룬룬이6mo ago
Hi @Hmza I was looking at your code because I'm trying to do something similar in my own code (i.e. building a query based on the args) but I'm running into TS errors
Type 'OrderedQuery<{ document: { _id: Id<"threads">; _creationTime: number; userId?: Id<"users"> | undefined; updatedAt?: number | undefined; pinnedAt?: number | undefined; pinId?: Id<"pins"> | undefined; ... 5 more ...; commentsCount: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"threads">; _creationTime: number; userId?: Id<"users"> | undefined; updatedAt?: number | undefined; pinnedAt?: number | undefined; pinId?: Id<"pins"> | undefined; ... 5 more ...; commentsCount: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchInd...': fullTableScan, withIndex, withSearchIndex, orderts(2739)
Type 'OrderedQuery<{ document: { _id: Id<"threads">; _creationTime: number; userId?: Id<"users"> | undefined; updatedAt?: number | undefined; pinnedAt?: number | undefined; pinId?: Id<"pins"> | undefined; ... 5 more ...; commentsCount: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"threads">; _creationTime: number; userId?: Id<"users"> | undefined; updatedAt?: number | undefined; pinnedAt?: number | undefined; pinId?: Id<"pins"> | undefined; ... 5 more ...; commentsCount: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchInd...': fullTableScan, withIndex, withSearchIndex, orderts(2739)
How would I type the queryBuilder to make sure the intermediary OrderedQuery and QueryInitializer types are accounted for?

Did you find this page helpful?