Reputation: 2232
I need to search documents inside a collection named blog which has text indexes defined for title, tags, summary and body:
@Document(collection="blog")
public class Blog {
@Id
private String id;
@TextIndexed(weight = 10)
private String title;
@TextIndexed(weight = 9)
private String tags;
@TextIndexed(weight = 8)
private String summary;
@TextIndexed(weight = 7)
private String body;
@TextScore
private Float score;
//getters and setters
}
Now, I have a requirement to perform text search on blog collection according to the following criteria:
For the 2nd case TextCriteria definition looks like:
TextCriteria criteria = TextCriteria.forDefaultLanguage().matching("SingleWord");
For the 3rd case, how to write criteria definition for the combination in single query:
query 1: db.articles.find( { $text: { $search: "\"coffee cake\"" } } ) //phrase search
query 2: db.articles.find( { $text: { $search: "coffee cake" } } ) //word search
Can I perform search with
query 1 OR query 2 with sorted result based on score.
Score should be higher for results matching for full phrase.
Upvotes: 3
Views: 11991
Reputation: 1852
MongoRepository also support TextCriteria queries on full text document. It is described here;
@Document
class FullTextDocument {
@Id String id;
@TextIndexed String title;
@TextIndexed String content;
@TextScore Float score;
}
interface FullTextRepository extends Repository<FullTextDocument, String> {
// Execute a full-text search and define sorting dynamically
List<FullTextDocument> findAllBy(TextCriteria criteria, Sort sort);
// Paginate over a full-text search result
Page<FullTextDocument> findAllBy(TextCriteria criteria, Pageable pageable);
// Combine a derived query with a full-text search
List<FullTextDocument> findByTitleOrderByScoreDesc(String title, TextCriteria criteria);
}
Sort sort = Sort.by("score");
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("spring", "data");
List<FullTextDocument> result = repository.findAllBy(criteria, sort);
criteria = TextCriteria.forDefaultLanguage().matching("film");
Page<FullTextDocument> page = repository.findAllBy(criteria, PageRequest.of(1, 1, sort));
List<FullTextDocument> result = repository.findByTitleOrderByScoreDesc("mongodb", criteria);
Upvotes: 1
Reputation: 2232
Spring Data MongoDB supports following operations for text search:
TextCriteria.forDefaultLanguage().matchingAny("search term1", "search term2")
TextCriteria.forDefaultLanguage().matching("search term")
TextCriteria.forDefaultLanguage().matchingPhrase("search term")
First criteria can perform text search for: search, text1, and text2 Second criteria can perform text search for: search, term Third criteria is for phrase search: 'search term'
A text query can be formed using above criteria:
Query query = TextQuery.queryText(TextCriteria.forDefaultLanguage().matchingAny("search term").sortByScore().with(new PageRequest(pageNum, docCount, new Sort(new Order(Sort.Direction.DESC, "score"))));
To use score (text search score) for sorting we need to add a field named score in the respective POJO:
@TextScore
private Float score;
We can add other filters on the text query as following:
query.addCriteria(Criteria.where("city").is("Delhi").and("country").is("India").and("price").lte(200.50).gte(100.50);
Finally to execute this query:
List<Product> products = mongoOperations.find(query, Product.class)
Mongodb by default assigns higher score to the phrase matches. Therefore one doesn't need to find phrase matches first in cases where phrase matches are required with higher scores and then normal text matches.
Upvotes: 5