Retrieve Total Document Count Before Pagination
I want to retrieve the total number of documents found before pagination takes place. However, I tried the following code and encountered an error.
error:
Uncaught Error: A query can only be chained once and can't be chained after iteration begins.
code:
51 Replies
you cant call collect and paginate on the same querybuilder
how...?
const giveMeNewVariable = () => {
let queryBuilder = ctx.db.query('skills');
queryBuilder = queryBuilder.withSearchIndex('title', (q) =>
q.search('title', title),
);
}
queryBuilder = queryBuilder.filter((q) =>
q.eq(q.field('isDeleted'), false),
);
// some code //
if (type !== undefined) {
queryBuilder = queryBuilder.filter((q) =>
q.eq(q.field('type'), type),
);
}
return queryBuilder ;
}
const totalFound = await giveMeNewVariable ().collect();
const results = await giveMeNewVariable().paginate(args.paginationOpts);
try something like this
imo, same logic...
not you get new variable
ok... let me try it
what you are doing
queryBuilder.collect().paginate()
make it also short
return ctx.db.query('skills').withSearchIndex('title', (q) =>
q.search('title', title),
).filter((q) => {
return q.eq(q.field('isDeleted'), false),
} )
same error....
Uncaught Error: A query can only be chained once and can't be chained after iteration begins.
i only want to search with title if title is truthy
i get it, but you are not allowed to chain the functions like that
i made it...
perfect
it works...
main point is to use same filters for 2 queries
you can also try something like this and see if it works:
query
.withSearchIndex("title", (q) => (title ? q.search("title", title) : q))
.filter((q) => q.eq(q.field("isDeleted"), false))
.filter((q) => type !== undefined ? q.eq(q.field('type'), type) : q );
cleaner
my search filters are conditional
i added the conditional inside the callbacks
okay... i didn't see
well we cannot return
q
onlydid you try?
yep
ok
full code....
nice
with dummy data this is public search
https://uxweaver-git-main-uxweaver.vercel.app/skills
looking good
thx
how to return totalFound
how to get
totalFound
from usePaginatedQuery
@jamalsoueidan do you have any idea?in the frontend you need two different queries
one special for pagination and one for the other
const { results, status, loadMore } = usePaginatedQuery(
api.message.paginate,
{ conversation: conversationId as Id<"conversation"> },
{ initialNumItems: 25 }
);
api.message.paginate cannot return other fields...
then i dont need
totalFound
I'm looking forward to the Convex team's response.I think they are going to sleep in few hours 😄
@M Zeeshan Sounds like you want a paginated query and an unpaginated one? just catching up
Paginated queries run the same query function multiple times, oncer per page
or you can do this...
there is no
count
methodits hiding from the documentation, you can just use length...
i want total number of docs found before pagination so i can tell user how many total docs were found with your applied filter
you use exactly same query just not paginate...
to use
.length
i need to use collect
first then .paginate
and still same problem i cannot send totalFound
to front-end as usePaginatedQuery
only gives results and if i modify results it throw erroryou modify the return value just like i did
i know you did... but
usePaginatedQuery
does not give it backahhh true
so you have to use 2 different queries
maybe convex team need to modify this behaviour
so we can pass more data along paginated results
Sorry to be late on this, yeah I think you want to use two queries. Paginated queries work quite differently: they run multiple times, once per page.
It's fine to use many conex queries in a web page or even the same React component because they all update at the same time: Convex provides a "consistent client view" so all these queries will update together.
you mean i need pagination conditionally with same filters
If you want a count of how many items there are in a paginated query, the client is the easiest place to do that (just the length of the list). If you want the number of elements in the entire paginated query that can requires accessing a lot of data; might need to do that in an action or with a denormalized counter to avoid needing to read every single row.
yeah if you use two queries, you'd want to pass the same arguments to both queries.
is this possible for convex team to modify
usePaginatedQuery
so it returns all else internal pagination datausePaginatedQuery is returning all the relevant data it has already
a paginated query doesn't know the total number of elements
if a full query would return 1 million elements, and the first page contained 200, the usePaginatedQuery hook doesn't know that there are 1 million elements
if it did it would have to traverse at minimum a million DB records, or have some denormalized state to keep track of how many there are elsewhere
i mean .... if i return from function
usePaginatedQuery must return all data but i only returns ( results, loadMore, status and isLoading )
does it make sense if i request for this feature?
So a paginated query runs many times, and the various pages of results get combined.
If you're returning more information, we'd have to figure out how to combined those fields between every run of that function
We could return the results from just the last page?
lets say there is unique prop e.g. results you can merge it everytime
I think you want a separate query here, that eliminates this merging logic. And it'll be less wasteful, instead of calculating it once per page you'll just be calculating it once
Consider factoring out your filter logic into a helper function that you can call from both the paginated query and this other query
sure
i will explain my point of view in another feature request thread
You can also write your own hook similar to usePaginatedQuery if there's something different you want here
its helpful
I wouldn't want to add this extra merging logic to the default usePaginatedQuery hook because when people use it they'll be doing the less efficient thing than writing a separate query, since every page of the query will independently calculate these values.