How to combine Spring Data MongoDB Query with full text search?

I recently upgraded to Spring Data MongoDB 1.6.0.RC1 which is very good and implements MongoDB 2.6 full text search functionality (huuurah!). My question is, how can I combine the Criteria and TextCriteria classes to generate complex queries?

Object model example:

{
  textProperty: "a text that is indexed for full text search",
  language:"en",
  aBooleanProperty: true,
  anIntegerProperty: 1
}

      

Query:

db.collection({ anIntegerProperty: 1,  $text: { $search: "indexed", $language: "en" } })

      

So how can I write the above query using Spring Data MongoDB classes?

+3


source to share


5 answers


Note: this post did not work previously but has now been fixed!

A TextCriteria

is CriteriaDefinition

and can therefore be used with the Query

following:



Quer query = Query.query(
  Criteria.where("aBooleanProperty").is(true).
  and(anIntegerProperty).is(1)).
  addCriteria(TextCriteria.
    forLanguage("en"). // effectively the same as forDefaultLanguage() here
    matching("a text that is indexed for full text search")));

List<YourDocumentType> result = mongoTemplate.findAll(query. YourDocumentType.class);

      

Put this using static imports for Query.query

and Criteria.where

, and it reads pretty fluently.

+3


source


Spring data supports MongoDB full text search queries. Consider in the example below, we are trying to find the text inside the textProperty field. You need to add @TextIndexed annotation for the field you want to find.

Model object:

public class TextExample {

@Id
private String id;

private String textProperty;

@TextIndexed
private String language;

private String aBooleanProperty;

private int anIntegerProperty;  

      

}

When building the TextCriteria you can provide a language parameter (I was looking at the default language which is English)



Request:

TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(
            "en");

    Query query = TextQuery.queryText(criteria).sortByScore();
    query.addCriteria(Criteria.where("anIntegerProperty").is(1));   

    List<TextExample> textExamples = mongoTemplate.find(query, TextExample.class);

      

This should return matching entries with language as "en" and anIntegerProperty as 1.

See the link for the TextCriteria documentation.

+2


source


According to my research on TextCriteria and Crities, there is no way to combine them using Spring Data MongoDB 1.6.2.RELEASE for aggregation (group by-aggregate function). I did this ugly hack for this:

private static class QueryHack extends Query implements CriteriaDefinition {
    @Override
    public DBObject getCriteriaObject() {
        return getQueryObject();
    }

    @Override
    public String getKey() {
        return null;
    }
}

      

And then:

QueryHack hack = new QueryHack();
hack.addCriteria(textCriteria).addCriteria(criteria);
MatchOperation match1 = new MatchOperation(hack); //Also it not possible to use static method match(textCriteria) - it takes Criteria only. 

      

I will add JIRA ticket to Spring MongoDB project.

+1


source


To create a Query object, you can combine criteria using a method Query.addCriteria()

that takes a parameter CriteriaDefinition

. And TextCriteria

, and Criteria

implement CriteriaDefinition

. For example, if you want to combine TextCriteria

and Criteria

, you can do it like this:

// Create TextCriteria
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("some key word"); 
// Build Query
Query query = TextQuery.queryText(criteria);
// Add the additional criteria to query
query.addCriteria(Criteria.where("field").is("fieldValue"));

      

0


source


You can create a composite index with Spring Data MongoDB like this:

@Document
@CompoundIndex(def = "{'anIntegerProperty': 1, 'textProperty': 'text'}")

      

Then create a repository:

@Repository
public interface TheDocuemntRepository extends MongoRepository<TheDocuemnt, String> {

    Stream<TheDocuemnt> findByAnIntegerPropertyOrderByScoreDesc(Integer anIntegerProperty, TextCriteria criteria);

}

      

Consider MongoDB documentation:

Composite Index

A composite index can include a text index key in combination with upstream / downstream index keys. However, these composite indexes have the following limitations:

  • A component text index cannot contain other special types of indexes such as fields with multiple keys or geospatial indexes.

  • If a composite text index includes keys that precede the text index key to perform a text search $, the query predicate must include conditions that match the previous keys.

Filter search results by language

If you also want to filter search results by language, you should try this approach: Multiple languages ​​example

An object

@CompoundIndex(def = "{'anIntegerProperty': 1, 'language': 1, 'textProperty': 'text'}")

      

Repository

Sort TEXT_SCORE_SORT = new Sort(Direction.DESC, "score");

@Query("{'anIntegerProperty': ?0, 'language': ?1, $text: {$search: ?2, $language: ?1}}")
Stream<TheDocuemnt> findTheDocument(Integer property, String language, String criteria, Sort sort);

      

0


source







All Articles