Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement MongoDB full text search pagination?

Tags:

java

mongodb

Now that my search query returns more than 100 documents, How do I implement pagination for all returned documents ? Is there A way to implement it withing mongoDB or I have to fetch all results in the server memory and implement pagination ( which does not seems reasonable ). Note that CommandResult is returned not a DBCursor !

    DBObject searchCommand = new BasicDBObject();
    searchCommand.put("text", collectionName);
    searchCommand.put("search", searchQuery);

    CommandResult commandResult = db.command(searchCommand);

Note: I am using Java.

like image 631
Adelin Avatar asked Apr 09 '13 11:04

Adelin


People also ask

Can MongoDB do full-text search?

MongoDB offers a full-text search solution, MongoDB Atlas Search, for data hosted on MongoDB Atlas.

How does text search work in MongoDB?

MongoDB text search uses the Snowball stemming library to reduce words to an expected root form (or stem) based on common language rules. Algorithmic stemming provides a quick reduction, but languages have exceptions (such as irregular or contradicting verb conjugation patterns) that can affect accuracy.

How do I search for a string in MongoDB?

Use the $text query operator to perform text searches on a collection with a text index. $text will tokenize the search string using whitespace and most punctuation as delimiters, and perform a logical OR of all such tokens in the search string.


2 Answers

The text search command does not have a skip option as at MongoDB 2.4, so any pagination will have to be implemented in your application code.

If you consider the behaviour of text search (which is to return results ranked based on relevance), a skip option would still have to cache or calculate the initial results to skip.

Efficiency

As far as efficient pagination in your application, a few suggestions would be:

  • cache the results of the initial search and slice page-sized subsets for your application to render
  • use a client-side plugin which presents the results from a single query in a nicely paginated view (for example using the jQuery DataTables plugin)

Number of results returned by limit

The default limit for text search is to return a maximum of 100 results. You can increase the limit, but keep in mind that the overall result document must still fit within the maximum BSON document size supported by your MongoDB server (16Mb, as at MongoDB 2.4). It's also worth considering that most users have a finite patience in searching through pages of results, so if you have a few hundred results it may better to suggest refining the search criteria.

Other options

If you have outgrown the current limitations of MongoDB 2.4's text search (which, incidentally, is still considered "experimental") you can always upgrade to a more full featured search product such as ElasticSearch or Apache Lucene. There are ways to feed your MongoDB data updates into external search products such as using an ElasticSearch River plugin or the Mongo Connector.

like image 109
Stennie Avatar answered Sep 23 '22 19:09

Stennie


For MongoDB v2.6+

Spring.IO MongoDB driver has recently added a TextCriteria, see $text $search your Documents with Spring Data MongoDB

TextCriteria criteria = TextCriteria.forDefaultLanguage()
  .matchingAny("coffee", "cake");

Query query = TextQuery.queryText(criteria)
  .sortByScore()
  .with(new PageRequest(0, 5));

List<CookingRecipe> recipes = template.find(query, CookingRecipe);

If you are using Grails MongoDB GORM plug-in, as of 3.0.2 the TextCriteria is not available in that API.

Instead you can use the mongodb api to perform the query and paginate:

// groovy/grails code... java code is very similar
BasicDBObject textSearch = new BasicDBObject('$text', new BasicDBObject('$search', 'cookie'))
BasicDBObject projection = new BasicDBObject('score', new BasicDBObject('$meta', 'textScore'))
BasicDBObject sort = new BasicDBObject('score', new BasicDBObject('$meta', 'textScore'))
DBCursor cursor = CookingRecipe.getCollection().find(textSearch, projection).sort(sort).skip(10).limit(5)
like image 26
GregHouston Avatar answered Sep 25 '22 19:09

GregHouston