Skip to main content

Searching

Hunch attempts to be a very comprehensive and powerful search engine.

The following are features are properties set on each search request, on the query property:

import { hunch } from 'hunch'
const search = hunch({ index: { /* the loaded compiled index */ } })
const query = {
q: 'search words',
facetExclude: { tags: [ 'cats' ] }
}
const results = search(query)

Helper Utilities

In addition to a programmatic API, Hunch offers a canonical mapping of URL query parameters to Hunch search parameters.

Using the --serve (or --serve 3030 for a custom port) flag will launch a simple HTTP server that uses these query parameters, for local development and testing.

info

These helper functions are entirely optional, you can make your own mapping of URL query parameters to Hunch, if you want!

To convert a query object or URLSearchParams object into a HunchJS search object, import the fromQuery function:

// Either from hunch directly
import { fromQuery } from 'hunch'
// Or as its own import
import { fromQuery } from 'hunch/from-query'
const { searchParams } = new URL('https://site.com?q=search%20words&facets[tags]=-cats')
const query = fromQuery(searchParams)
// => { q: 'search words', facetExclude: { tags: [ 'cats' ] } }

Hunch Search to Query String

To convert a HunchJS search object into a query string (no leading ? character), import the toQuery function:

// Either from hunch directly
import { toQuery } from 'hunch'
// Or as its own import
import { toQuery } from 'hunch/to-query'
const query = toQuery({ q: 'search words', facetExclude: { tags: [ 'cats' ] } })
// => facets[tags]=-cats&q=search%20words

Search Parameters

Hunch supports the following features:


Boost (Examples)

Boost the ranking value of some metadata properties.

Programmatic

  • Name: boost
  • Type: Object<String,Number> - The key is the metadata key, the number is the amount to boost.

Example:

{ "boost": { "title": 2, "summary": 3 } }

Exact Phrase (Examples)

Same as the Full Text Lookup but use quote marks to limit the results to an exact-phrase match.

Single or double quotes work fine, you can even use both, but they need to be correctly paired.

Example:

{ "q": "cars 'wireless chargers'" }

This will return results containing the words cars, wireless, and chargers anywhere in searchable fields, and the phrase wireless chargers must exist in the field as well.

Word fuzziness is not used with exact-phrase queries, but results do ignore upper/lower case differences.


By ID (Examples)

Fetch a single item by the _id, which is the filename.

info

All other search parameters are ignored when this one is set.

The output from Hunch is different for a request by ID (see the search results docs for details).

Example:

{
"item": {
"_id": "posts/2023-01-03-cool-cats.md",
"title": "My Cool Cats",
"_chunks": [
{ "content": "Many words about cats." }
]
}
}

Programmatic

  • Name: id
  • Type: String - The identifier of the item to return.

Example:

{ "id": "posts/2023-01-03-cool-cats.md" }

Query Parameter

  • Name: id
  • Type: String - The identifier of the item to return.
{ "id": "posts/2023-01-03-cool-cats.md" }

Facet Matching (Examples)

Filter by content facet values, e.g. filter by content containing a tag property with cats and not dogs.

Programmatic

There are three properties for facet matching:

one for inclusive (the content must include it), the other for excluding (the content must not include it).

  • Names:
    • facetMustMatch - The item must contain all specified facet key-values.
    • facetMustMatchAny - The item must contain any of the specified facet key-values.
    • facetMustNotMatch - The item must contain none of the specified facet key-values.
  • Type: Object<String,Array<String>> - The key is the metadata key to filter by, the value is a list of metadata values.

Example:

{
"facetMustMatch": { "tags": [ "cats" ] },
"facetMustMatchAny": { "tags": [ "rabbits" ] },
"facetMustNotMatch": { "tags": [ "dogs" ] }
}

Query Parameter

The query parameter combines the three by using the - prefix as exclusive and ~ for the match-any.

  • Name: facets[$KEY] - The $KEY is the metadata key used to filter.
  • Type: String - A comma seperated list of key values, where: 1) a - prefix indicates exclude that value, 2) a ~ prefix indicates match-any.

Example:

{ "facets[tags]": "cats,~rabbits,-dogs" }

Full Text Lookup (Examples)

Find records with the exact words.

Query Parameter

  • Name: q
  • Type: String

Example:

{ "q": "exact words" }

Programmatic

Example:

  • Name: q
  • Type: String

Example:

{ "q": "exact words" }

Specify a fuzziness to the text query, to find records with misspelled or similar words. The fuzziness value must be positive and greater than 0.

E.g. to find cats and kats you might use q=cats&fuzzy=0.8

Programmatic

  • Name: fuzzy
  • Type: Float

Example:

{ "fuzzy": 0.8 }

Query Parameter

  • Name: fuzzy
  • Type: String - Converted to a float using parseFloat.

Example:

{ "fuzzy": "0.8" }

Get Facets (Examples)

Retrieve the full facets map by not setting a query parameter.

This effectively gives you the entire data set, so you'll get up to a full page of results back, with the facet map filled for all data.

You can specify the page size as 0 if you want no items returned, but this is not required.

Programmatic

Example:

{ "pageSize": 0 }

Query Parameter

Example:

{ "page[size]": "0" }

Pagination (Examples)

Specify how many results to return per query. Hunch uses a page size and offset:

  • Size: the number of results to include. Default: 15
  • Offset: the number of pages to offset, as a zero-index. E.g. if there were 3 pages, the offsets would be 0, 1, and 2.

Specify how many results with page[size] and a pagination offset with page[offset]

maxPageSize

To limit the maximum page size (e.g. to prevent page[size]=Infinity attacks) you can pass in a limit as maxPageSize on instantiation.

Default: 100

import { hunch } from 'hunch'
const search = hunch({
index: { /* the loaded compiled index */ },
maxPageSize: 25,
})
// ...

Programmatic

  • Name: pageSize and pageOffset
  • Type: Integer

Example:

{ "pageSize": 4, "pageOffset": 2 }

Query Parameter

  • Name: page[size] and page[offset]
  • Type: String - Converted using parseInt

Example:

{ "page[size]": "4", "page[offset]": "2" }

Prefix (Examples)

To find both motorcycle and motocross you might use moto as the query text, and specify it as a prefix.

Note: this property applies to the whole query, e.g. word1 word2 will look for word1 word2* not word1* and word2*.

Programmatic

  • Name: prefix
  • Type: Boolean - Anything truthy will be interpreted as true, all other values as false.

Example:

{ "prefix": true }

Query Parameter

  • Name: prefix
  • Type: String - Must be exactly true or false.

Example:

{ "prefix": "true" }

Return Specific Facets (Examples)

Alter the facet map included on the results response. Hunch defaults to returning a facet map of only the facets found in the search results.

Programmatic

  • Name: includeFacets
  • Type: Array<String> - The list of facet keys to include in the facet map.

Example:

{ "includeFacets": [ "title", "summary" ] }
info

Use the * facet name to include all facets across all searchable items:

{ "includeFacets": [ "*" ] }

Query Parameter

  • Name: include[facets]
  • Type: String - Comma seperated list of facet keys to include in the facet map.

Example:

{ "include[fields]": "title,summary" }
info

Use the * facet name to include all facets across all searchable items:

{ "include[fields]": "*" }

Return Specific Fields (Examples)

Limit the fields of the returned result items. Hunch defaults to returning every field.

caution

The _id field will always be returned, but specifying any field overrides the default entirely, which means you need to specify all fields if you specify any.

Programmatic

  • Name: includeFields
  • Type: Array<String> - The list of metadata keys to return.

Example:

{ "includeFields": [ "title", "summary" ] }

Query Parameter

  • Name: include[fields]
  • Type: String - Comma seperated list of metadata keys to return.

Example:

{ "include[fields]": "title,summary" }

Search Specific Fields (Examples)

Limit the text query to one or more metadata properties. (Hunch defaults to searching every field configured as searchable.)

caution

Specifying any field overrides the default entirely, which means you need to specify all fields if you specify any.

info

To specify the main content field, use content.

Programmatic

  • Name: fields
  • Type: Array<String> - The list of metadata keys to search.

Example:

{ "fields": [ "title", "summary" ] }

Query Parameter

  • Name: fields
  • Type: String - Comma seperated list of metadata keys to search.

Example:

{ "fields": "title,summary" }

Score (Examples)

The search results include a ranking value named _score, which is the relevance that the search engine gives to each result.


Snippet (Examples)

Specify how much context to include around the found query text.

caution

In version 0.2 of Hunch, this implementation is not particularly context-aware: the number you provide is up to the number of characters at the search term to include, so it doesn't start or end at word boundaries. Future versions of Hunch are planned to be more context aware.

info

To specify the main content field, use content as the metadata key.

Programmatic

  • Name: snippet
  • Type: Object<String,Number> - The key is the metadata key, the number is the maximum number of characters to include near the query term.

Example:

{ "snippet": { "title": 50, "content": 120 } }

Query Parameter

  • Name: snippet[$KEY] - The $KEY is the metadata key.
  • Type: String - The number is the maximum number of characters to include. Converted to a number using parseInt.

Example:

{ "snippet[title]": "50", "snippet[content]": "120" }

Sort (Examples)

Specify a list of ordered sort objects when making a query, to sort the search results prior to pagination and faceting.

The query normalization function will turn a comma-separated list of keys into a list of sort objects.

Because sorting can be content-specific, you can also pass in a sort function when instantiating Hunch. The function is supplied with the complete list of search result items and the normalized query object, and should return the sorted list.

Example:

import { hunch } from 'hunch'
const search = hunch({
index: { /* the loaded compiled index */ },
sort: ({ items, query }) => {
return query.sort === 'date'
? items.sort((a, b) => a.published - b.published)
: items
}
})
const query = {
q: 'search words',
sort: 'date',
}
const results = search(query)

Programmatic

  • Name: sort
  • Type: Array<{ key: String, descending: Boolean }> - An ordered list of metadata keys to use in sorting.

Example:

{
"sort": [
{ "key": "published", "descending": false },
{ "key": "modified", "descending": true }
]
}

Query Parameter

  • Name: sort
  • Type: String - A comma-separated list of ordered sort keys. To mark as descending, prefix with a dash (-).

Example:

{ "sort": "published,-modified" }

Suggest (Examples)

Instead of search results, Hunch can give you back suggested search strings based on your indexed data.

For example, the query text arch might suggest archery sport and march madness as better search queries.

info

The output from Hunch is different for a suggestion (see the search results docs for details). The output looks like this:

Example:

{
"suggestions": [
{ "q": "archery sport", "score": 1.305 },
{ "q": "march madness", "score": 0.073 }
]
}

Programmatic

  • Name: suggest
  • Type: Boolean - Anything truthy will be interpreted as true, all other values as false.

Example:

{ "suggest": true }

Query Parameter

  • Name: suggest
  • Type: String - Must be exactly true or false.

Example:

{ "suggest": "true" }