JSearch in 5 Minutes

Aries Yuwono
Last updated October 15, 2015


JSearch is a Server-side and high-level Javascript API that makes common search tasks (search, facets, and aggregates) easy. It's an easier path to learn than the cts.* API for novice users and a shortcut for applying what you already know for more advanced users. JSearch is available in MarkLogic 8-0.4 and above. This tutorial will provide a quick introduction to using the API.

Indexes setup

Before we begin with JSearch, let's set up our database with the indexes that we will use for the examples. We're using the Documents database for our examples, but feel free to create a new database (with a forest) of your choice if you wish. You can run this JavaScript code in Query Console (http://localhost:8000/qconsole) with the Content Source pointing to the Documents database to apply the setup.


This city dataset contains JSON and XML documents. They are inserted into different collections (e.g. "america", "asia", ...). Some of the documents also have quality metadata value. Run this script in Query Console against Documents database to insert the data.

Let's say we want to search cities in the "america" continent; we can do so by doing search with a collection scope. Calling sr.documents() without any where() clause would match all documents in the database, but because we have specified the collections() scope, this query will match all documents in the "america" collection.

Our output will return the two documents in the "america" collection.

Adding where() will narrow the search.

The output should return one document that has "london" as the "city".

With orderBy(), you can sort the results based on specified index.

The output will be 5 documents in this order: "new york", "new jersey", "london", "cape town", "beijing".

Adding slice() will apply pagination on the result.

JSearch provides several ways to tailor the results of your search. The map() provides built-in functions such as snippet and extract. Here is an example of using snippets.

The returned document will include match text highlighting.

Extract will allow you to return a portion of document with specified path.

Instead of the entire content of the document, the query will only return the extracted portion.

You can write your own function for the mapper to produce a custom result.

This mapper will transform the result to:

Alternatively to map(), you can use reduce() to reduce the result.

This will reduce the result.

Add withOptions() to toggle various options on/off.

You can parse a query string using cts.parse().

This should give you "london" and "new york".

Search using values() to look up the values in a range index over documents. In this example, where() and match() are used to limit the result.

The result should return an array of values, in this case: ["cape town", "london"]

Adding aggregate() on values will apply aggregate functions against an index. For example, find the average, maximum, and minimum distance of the cities.

This will give you:

You can create range indexes and apply bucket names on them. For example, create facets on "date" and "popularity" with user-defined bucket names. Facets are quite similar to values but it provides a search report. These help users explore the data set.

The result will give you the frequencies and the values on the buckets.

Similar to values lookups, you can look up words in word lexicons over documents. For example, find all words within "city" that has the letter "n".

This should give you:

You can do geospatial searches on your data using points, circles, boxes, or polygons.

For more features, please check the JSearch function documentation.


  • I believe at the top of this guide in the code snippet that sets the indexes, there is a distanceIndex created but not added. This will cause trouble when you use aggregate() to calculate min, max, avg distance.