Guides
Searching
Queries, filters, facets, sorting, paging, and highlighting, from the browser or your server.
The browser and server SDKs take the same search request. The examples use the browser client:
import { SearchBrowserClient } from "@findlane/browser"
const client = new SearchBrowserClient({ publicId: "pub_your_public_id" })
const results = await client.search<Product>({
q: "rain jacket",
filters: { "brand.name": { in: ["Northwind", "Acme"] }, price: { lte: 200 }, inStock: true },
facets: ["brand.name", "categories"],
sort: "price-asc",
limit: 24,
highlight: true,
})Queries
q is up to 200 characters. Every word must match one of the searchable fields, with typo tolerance and synonyms, and results rank by how well and where they match. An empty q returns every record that passes the filters, in the chosen sort.
Filters
filters keeps records whose fields match, for up to 20 facet or filter fields. All filters must match.
| Filter | Keeps records where the field |
|---|---|
{ inStock: true } | Is true. Text and numbers work the same way. |
{ "brand.name": { in: ["Acme", "Northwind"] } } | Is any of up to 100 values |
{ price: { gte: 50, lte: 200 } } | Is within a range; either bound can be left out. Numbers only. |
A list field matches when any of its values does.
Facets
facets asks for value counts of up to eight facet fields:
results.facets
// { "brand.name": { Acme: 12, Northwind: 7 }, categories: { Jackets: 15, Shoes: 4 } }To show counts for other values of a field that is filtered, as a list of checkboxes usually does, ask again without that field's filter.
Sorting
sort is a sort ID from the index's settings, or relevance. Without one, the index's default sort applies. results.sort says which sort was used.
Paging and counts
limit is the number of hits per request (20 by default; up to 100 from your server and 50 from browsers), and offset skips hits, up to 1,000.
By default, total and facet counts cover the returned page when a query matches more, which keeps searches fast:
hasMoreistruewhen there are more hits after this page.totalRelationis"gte"whentotalis a lower bound.
Set countMode: "exact" for the total number of matches, and facetMode: "exact" for facet counts across all of them. They cost more time on broad queries, so ask for them when you show them, such as on the first page of results.
Highlighting
highlight: true returns each hit's matched searchable fields with the matched words in <mark> tags, under highlights. The values are HTML-escaped, so they are safe to insert as HTML. List fields give one string per value.
results.hits[0].highlights
// { title: "Waterproof <mark>rain</mark> <mark>jacket</mark>" }Choose other tags with highlight: { preTag: "<em>", postTag: "</em>" }.
Fewer fields
attributesToRetrieve returns only the listed fields of each record, such as ["title", "price", "image"], which makes responses smaller. It doesn't keep the other fields private; see Security.
Responses
{
hits: [{ id: "sku-2", score: 12.4, record: { objectID: "sku-2", title: "Waterproof rain jacket", ... } }],
total: 1,
totalRelation: "eq",
hasMore: false,
facets: { "brand.name": { Northwind: 1 } },
sort: "relevance",
tookMs: 6,
}Search as you type
- Cancel the previous request when the query changes: pass
{ signal }to the browser client, or a signal as the server client's second argument. - Wait about 100 to 150 ms after a keystroke before searching. Every request counts toward your plan's monthly searches.
- Keep the first request light: exact counts and many facets can wait for the results page.