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:
- Check the user input whether it contains more than one word.
- If searchKey is single word perform text search and return sorted response according the weight.
- If searchKey contains more than one word the perform search for full PHRASE OR any word within the PHRASE.
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.
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:
To use score (text search score) for sorting we need to add a field named score in the respective POJO:
We can add other filters on the text query as following:
Finally to execute this query:
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.