-
-
Notifications
You must be signed in to change notification settings - Fork 752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
result.total does not account for params.pipeline #3057
Comments
@xsl777, thanks for reporting. This definitely sounds like a bug, but not the one that you might think. Pagination shouldn't work at all when using the aggregation framework queries. The aggregation framework can return any type of response, even non-countable and non-page-able ones. So there's not really a reliable way for us to calculate the number of documents. Some queries will return a single document (not in an array) containing a single primitive, and it doesn't even have to match your schema. So if you're getting a response back that includes pagination, the short-term fix is for us to disable pagination for aggregation framework queries. The long-term fix is to look at the feasibility of performing some query analysis on the pipeline stages to see if we can enable pagination. That will take some research, which is why it's long-term. |
This also brings up a good point that I should specify this in the docs. |
We might be able to enable pagination whenever the The |
Here's the code causing the bug: https://github.com/feathersjs/feathers/blob/dove/packages/mongodb/src/adapter.ts#L243-L255. I'm going to see if I can figure out a good way to auto-enable pagination in a reliable way, because I'd love for it to work as you described. |
I supposed this line could be updated with the
Also, there could probably only be one |
i have same problem find(params?: ServiceParams & {
paginate?: PaginationOptions;
}): Promise<Paginated<MediaAd>>;
find(params?: ServiceParams & {
paginate: false;
}): Promise<MediaAd[]>;
async find(params?: any): Promise<Paginated<MediaAd> | MediaAd[]> {
const rsp = await super.find({
...params,
})
if (rsp.total && params && Array.isArray(params.pipeline)) {
const model = await this.getModel(params);
const count = await model.aggregate([
...params.pipeline,
{
$count: "mediaManagerId"
},
{
$project:{
count:'$mediaManagerId'
}
}
])
const rows = await count.toArray()
rsp.total = rows[0]['count']
}
return rsp;
} |
I think the solution here is to remove |
The actual bug is happening here: https://github.com/feathersjs/feathers/blob/dove/packages/mongodb/src/adapter.ts#L314 We call On the other side, the I think the ideal solution is to use a similar branching like const getTotal = () => {
return params.pipeline ? this.countAggregate(params) : this.countDocuments(params)
}
...
const [data, total] = await Promise.all([getData(), getTotal(params)]) the we can remove the async countAggregate(params: ServiceParams) {
const model = await this.getModel(params)
const pipeline = params.pipeline || []
const index = pipeline.findIndex((stage: Document) => stage.$feathers)
const before = index >= 0 ? pipeline.slice(0, index) : []
const after = index >= 0 ? pipeline.slice(index + 1) : pipeline
const res = await model.aggregate([...before, ...after, { $count: 'count' }], params.mongodb).then((result) => result.toArray())
return res?.[0]?.count ?? 0
} |
I believe this is fixed now via #3541 |
Steps to reproduce
pre.37, db: MongoDB
(context) => {
context.params.pipeline = [{ $match: { foo: 'bar' } }]
return context
}
The result.data array is correct
result.total should be equal to the number of db records where foo is equal to 'bar', but it's equal to the total number of records as if no custom pipeline specified
The text was updated successfully, but these errors were encountered: