简体   繁体   中英

Spring + MongoDB custom queries running slow

I have a MongoDB collection (called "Products") of ~7000 documents, hosted on a Mongo Atlas shared cluster, looking somewhat like this:

{
   identifier: 123,
   archived: true,

   /* Some other properties.. */
}

Attempting to run simple queries on the above collection in a manner such as:

mongoTemplate.find(
      new Query().addCriteria(Criteria.where("archived").is(false)), 
      Product.class, 
      "Products");

leads to an extremely high execution time, 8~9 seconds on both the local instance as well as deployed (Heroku) version. However, when running the same query directly from the MongoRepository<> , eg repository.findByArchived(false) , the query runs almost instantaneously (as it would do in the mongo CLI).

Am I missing out some additional configuration that is preventing mongoTemplate from running queries in a smoother manner like the pre-configured MongoRepository (eg some bson/POJO encoding)? Any help on this would be greatly appreciated!

Its hard to tell what exactly causing the slowness of custom queries but atlas provides several tools to help analyze slow queries being executed on your clusters.

The Performance Advisor monitors queries that MongoDB considers slow and suggests new indexes to improve query performance. Do give it a read - Performance Advisor

Although there's no way to answer exactly what you need to change, if the connections are ok, there's a chance your code is not optimized, I would advise you to check the latest changes made to the code (if the database has ~7000 documents I will assume that it was working properly until recently).

Also, something like this could happen: Why is processing a sorted array faster than processing an unsorted array?

Using a Criteria Query with MongoTemplate

I might have misinterpreted your problem area completely, but I hope that I'm not totally lost. To me it looks as if you want a list of projects in a series where the archived property is false ?

Unsure of what some other properties mean, but with this data:

    {
       identifier: 123,
       archived: true,
    
       /* Some other properties.. */
    }

To me it looks like you would get much better performance, readability and results by using Projection with the MongoTemplate to include only the properties that you actually want and exclude the rest.

So instead of writing:


mongoTemplate.find(
      new Query().addCriteria(Criteria.where("archived").is(false)), 
      Product.class, 
      "Products");

You'd probably be better off doing something like this:


public List findActive() {
    Query query = new Query();
    // Here you exclude those unrelated 'other properties'
    query.fields().exclude("prop1").exclude("prop2");
    query.addCriteria(Criteria.where("archived").is(false));
        
    return mongoTemplate.find(query, Product.class);
}

Anyway, as I said, please tell me if I've misunderstood the problem. If so I'll correct the errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM