Skip to content

count() $maxTimeMS not work #4374

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

Closed
zhaohuiio opened this issue Apr 26, 2023 · 6 comments
Closed

count() $maxTimeMS not work #4374

zhaohuiio opened this issue Apr 26, 2023 · 6 comments
Labels
type: bug A general bug

Comments

@zhaohuiio
Copy link

zhaohuiio commented Apr 26, 2023

mongodb version 3.6.23
jdk 11
system: MacOS 12.4

Criteria criteria = Criteria.where("token").is("true");
Query query = new Query(criteria).maxTimeMsec(1000);;
long count = mongoTemplate.count(query, DBObject.class, "public_leads");

The desired effect is that after 1 second of execution, if it doesn't compute, then immediately break it. But this will not happen, and count() will complete the entire evaluation without being interrupted by a query timeout

db.collection.count({query}, {maxTimeMS: 1000})
Native mongodb js queries work, but not in the framework, I tried the two versions respectively, spring-data-mongodb version: 3.4.11 , 4.0.5 will be repeated

Criteria criteria = Criteria.where("token").is("true");
Query query = new Query(criteria).maxTimeMsec(1000);
List list = mongoTemplate.find(query, DBObject.class, "public_leads");

There's no problem with using it that way

@zhaohuiio zhaohuiio reopened this Apr 26, 2023
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 26, 2023
@zhaohuiio
Copy link
Author

zhaohuiio commented Apr 27, 2023

db.public_leads.count({token:"true"}, {maxTimeMS: 1000})
Generate logs in mongodb using native queries Include $maxTimeMS in the log discovery query statement
图片

springboot TestCode( Base on spring-data-mongodb version: 4.0.5 )

public long test(){
        Criteria criteria = Criteria.where("token").is("true");
        Query query = new Query(criteria).maxTimeMsec(5);;
        Object count = mongoTemplate.count(query, DBObject.class, "public_leads");
        return 0;
}

Execute the above code to generate logs in mongodb,count() uses aggregation at the bottom of the framework

图片

@zhaohuiio
Copy link
Author

Add maxTimeMS to AggregationOptions [DATAMONGO-2390] #3249

Based on this PR, it seems that aggregation is needed to solve this problem

@christophstrobl
Copy link
Member

@zhaohuiio thank you for the additional explanation. I see, maxTimeMsec is from the query is not carried forward to CountOptions#maxTime when performing an exact count.

@christophstrobl christophstrobl added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Apr 27, 2023
@zhaohuiio
Copy link
Author

zhaohuiio commented Apr 27, 2023

I found a solution( Base on spring-data-mongodb version: 4.0.5 )

public long test(){
        Duration duration = Duration.ofMillis(2000);
        AggregationOptions options = Aggregation.newAggregationOptions().maxTime(duration).build();
        Criteria criteria = Criteria.where("token").is("true");
        Aggregation aggregationCount = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group().count().as("count")
        );
        Aggregation aggregation = aggregationCount.withOptions(options);
        List record = mongoTemplate.aggregate(aggregation, "public_leads", DBObject.class).getMappedResults();
        BasicDBObject obj = (BasicDBObject)record.get(0);
        String count = obj.get("count") + "";
        return Long.valueOf(count);
    }

But In earlier versions, this method did not work because Aggregation.newAggregationOptions().maxTime() did not be provided

@zhaohuiio
Copy link
Author

zhaohuiio commented Apr 27, 2023

One last question, What I don't understand here is why the count method of the high version of spring-data-mongodb should be implemented by aggregation at the bottom !

public long test(){
        Criteria criteria = Criteria.where("token").is("true");
        Query query = new Query(criteria).maxTimeMsec(1000);;
        long count = mongoTemplate.count(query, DBObject.class, "public_leads");
        return count;
 }

Execute code, generated log

2023-04-27T16:31:17.211+0800 I COMMAND [conn3320915] command xxx.public_leads appName: "MongoDB Shell" command: aggregate { aggregate: "public_leads", pipeline: [ { $match: { token: "true" } }, { $group: { _id: 1.0, count: { $sum: 1.0 } } } ], cursor: {}, lsid: { id: UUID("e1c3816c-0fff-49a1-9cb7-e6cf1096c371") }, $clusterTime: { clusterTime: Timestamp(1682584274, 1), signature: { hash: BinData(0, 0000000000000000000000000000000000000000), keyId: 0 } }, $readPreference: { mode: "secondaryPreferred" }, $db: "xxx" } planSummary: COUNT_SCAN { token: 1, user_company_id: 1, discard_time: 1 } keysExamined:3852981 docsExamined:0 cursorExhausted:1 numYields:30104 nreturned:1 reslen:257 locks:{ Global: { acquireCount: { r: 60212 } }, Database: { acquireCount: { r: 30106 } }, Collection: { acquireCount: { r: 30106 } } } protocol:op_msg 2515ms

After many times of verification, the efficiency of the old version of mongodb is higher than that of the new version using aggregation to calculate values.

db.public_leads.count({token:"true"}, {maxTimeMS: 5000})

2.04s

db.getCollection('public_leads').aggregate([          
{$match:{token:"true"}},
{$group:{_id:1, count: {$sum:1}}}
])          

2.63s

图片

图片

Looking forward to your reply !

@christophstrobl
Copy link
Member

Count can operate upon collection statistics which is fast but may return an inaccurate result. Details can be found in the MongoDB documentation.

@mp911de mp911de added this to the 3.4.12 (2021.2.12) milestone May 11, 2023
mp911de pushed a commit that referenced this issue May 11, 2023
This commit makes sure to forward maxTimeMsec and comment options from the query to the CountOptions.

Closes: #4374
Original pull request: #4378
mp911de added a commit that referenced this issue May 11, 2023
Introduce has…() and getRequired…() methods for comment and max time limit to remove code duplications.

See #4374
Original pull request: #4378
mp911de pushed a commit that referenced this issue May 11, 2023
This commit makes sure to forward maxTimeMsec and comment options from the query to the CountOptions.

Closes: #4374
Original pull request: #4378
mp911de added a commit that referenced this issue May 11, 2023
Introduce has…() and getRequired…() methods for comment and max time limit to remove code duplications.

See #4374
Original pull request: #4378
mp911de pushed a commit that referenced this issue May 11, 2023
This commit makes sure to forward maxTimeMsec and comment options from the query to the CountOptions.

Closes: #4374
Original pull request: #4378
mp911de added a commit that referenced this issue May 11, 2023
Introduce has…() and getRequired…() methods for comment and max time limit to remove code duplications.

See #4374
Original pull request: #4378
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants