MarkLogic is both a database and a search engine. Sometimes, you know you only want one result from your search. What’s a good way to do that?
const query = ...; // foreshadowing -- there's a better way! cts.search(query).toArray().slice(0, 1)
We get the results of our search, change the results from a Sequence to an Array, and take the first one. Simple — but not the way we should do this. How do we know? We ask MarkLogic, of course. Instead of the above, let’s evaluate the following in Query Console (note: if your query will hit a large number of documents, maybe don’t run this in Query Console).
const query = ...; cts.search(query).toArray().slice(0, 1); xdmp.queryMeters()
Looking at the queryMeters output, we see some interesting things, including cache hits and misses. Toward the end of the response, there’s a JSON property called “documents”, which is an array of objects identifying the URIs that the query loaded. As written, that array will include all results from the search, not just the one that we want to get.
We want to tell MarkLogic to just return the first one. For some MarkLogic functions, you can specify an option “limit=1”. The
cts.search() function doesn’t have that option.
cts.search returns a Sequence, a data structure that is similar to an array in some ways, but not quite the same. In XQuery, there are a few ways we could wrap a call to
cts:search() to tell MarkLogic that we only wanted a certain number of results:
cts:search(fn:doc(), $query)[1 to 10] fn:subsequence(cts:search(fn:doc(), $query), 1, 10)
MarkLogic sees what parts of the Sequence we want and optimizes to only return those. Calling
xdmp:query-meters() confirms that.
Yes, yes we can.
fn.subsequence(cts.search(query), 1, 10)
xdmp.queryMeters() tells us that we’re only bringing back the ten documents (remember that a Sequence starts at index 1, while an Array starts at index 0).
Knowing that Sequence optimizations influence our searches, we’ve got a real simple way to get just that first result:
const query = ...; fn.head(cts.search(query))
Again, we turn to
xdmp.queryMeters() and find just one item in the documents array. Just what we need!