If you're reading this, you probably landed here from a search engine.

And the reason you landed here from a search engine is because you need to handle full text searching in your Spring Boot application.

But not full text searching alone. You also need to add another criteria to your query. And you're not sure how to do it.

I will therefore show you how to do it.

Start With MongoTemplate

If you're one of those "I just got here from the Google" folks, odds are better than even money that you're using MongoRepository to handle your full text searching.

And that works just fine. When you only want to do full text searching.

But what if you want to query with some other criteria as well? That's a little trickier.

So I recommend you move your query to a service that uses MongoTemplate.

We've Been Here Before

I've already explained how to handle full text searching with MongoTemplate in a previous guide. If you're totally new to the concept, you should start there.

Once you're back here, you'll already know that the code I'll share is part of what's running the blog that you're reading right now.

In other words, I'm rolling out full text search capabilities on this blog and I'm showing you how I'm doing it.

I've got the full text search part handled, but there's one problem. A simple full text search retrieves all documents, whether they're published or in draft status.

I don't want to return documents in draft status. So I need to add another criteria to the query.

Fortunately, it's a breeze.

The Updated Service

Here's the new service:

@Service
public class BlogService {

    private static final Logger LOG = LoggerFactory.getLogger(BlogService.class);
 
    
    @Autowired
    private MongoTemplate mongoTemplate;
    
    
    public Page<BlogPost> fullTextSearch(String searchPhrase, Pageable pageable) {
        TextCriteria criteria = TextCriteria
                                    .forDefaultLanguage()
                                    .matchingPhrase(searchPhrase);
        
        Query query = TextQuery
                        .queryText(criteria)
                        .addCriteria(Criteria.where("status").is(BlogPostStatus.PUBLISHED))
                        .with(pageable)
                        .skip(pageable.getPageSize() * pageable.getPageNumber())
                        .limit(pageable.getPageSize());
        
        List<BlogPost> posts = mongoTemplate.find(query, BlogPost.class);
        long count = mongoTemplate.count(query.skip(-1).limit(-1), BlogPost.class);
        
        Page<BlogPost> resultPage = new PageImpl<BlogPost>(posts, pageable, count);
        
        return resultPage;
    }    
}

If you were also here for my guide on pagination using MongoTemplate, then you know that the code above is strikingly similar to the previous version of the service.

In fact, the difference is just one (1) line.

Check out the addCriteria() method that gets chained in with the other methods that build the Query object.

That's the additional criteria.

And that's all you gotta do if you want to add more criteria to your full text search queries.

You can string together as many addCriteria() methods as you want. Just keep in mind the search will only return documents that match all the criteria.

In the example above, the query is looking for documents with a "status" property set to "PUBLISHED." That's in addition to the full text search criteria.

So now the query will only return published documents that match the search string.

Yes. It's that easy.

As I noted in the previous guide, you can give that code a test drive like so:

for (int i=0;i<3;i++) {
    Pageable pageable = PageRequest.of(i, 5, Sort.by("score").descending());
    Page<BlogPost> posts = blogService.fullTextSearch("spring boot", pageable);

    System.err.println(posts.getNumber());
    System.err.println(posts.getNumberOfElements());
    System.err.println(posts.getTotalPages());

    posts.forEach(post -> {
        System.err.println(post.getTitle() + " " + post.getScore());
        //System.err.println(post.getSlug());
    });
    
    System.err.println("---");
}

That's going to print out titles and scores for the first three pages of documents that match.

Again, check out the guide on pagination if you need more info about how that works.

Wrapping It Up

That wasn't so bad, was it?

Now you know how to handle full text searches that include additional criteria. 

All that's left for you to do is apply what you've learned here to your own Spring Boot solutions.

Have fun!

Photo by Black ice from Pexels