lucaong / minisearch

Tiny and powerful JavaScript full-text search engine for browser and Node
https://lucaong.github.io/minisearch/
MIT License
4.64k stars 133 forks source link

Prefix search enabled/disabled per search field #227

Closed Thomas-1985 closed 1 year ago

Thomas-1985 commented 1 year ago

Hi

Is ist possible to enable the prefix search per search field? I am working on a project where text as well as numbers (prices) ist searchable. Prefix search for the text makes sense and is needed, however when it comes to searching prices and i search for i.e. 50 i also get 500 which is not desired.

Is there a way to fix this and if so, how?

lucaong commented 1 year ago

EDIT: this answer is incorrect, see my following comment. Leaving it for reference.

Hi @Thomas-1985 , Yes, that is possible: the prefix search option can accept a function that takes the field name and term, and can return a boolean. You can therefore return true for the text fields, and false for the prices (the fuzzy option also can accept a similar function).

Example (edit: NOT CORRECT, see comment below)

const documents = [
  {
    id: 1,
    text: "Some example text",
    price: "123.21 €"
  },
  // more documents…
]

const miniSearch = new MiniSearch({
  fields: ['text', 'price'],
  searchOptions: {
    prefix: (fieldName) => fieldName !== 'price'
  }
})

// These will yield results
miniSearch.search('examp')
miniSearch.search('123.21')

// This will NOT yield results, because prefix search is disabled for price
miniSearch.search('12')
lucaong commented 1 year ago

Sorry! Discard what I said, the function form of the prefix option does not take the field name as argument, my bad. I am out, typing from my phone, and misremembered the API.

This is a missing feature that could be added in the future.

For the moment, the best way is to use a query combination to specify two different searches. The QueryCombination tree-like syntax is intended as a programmatic API, so it’s a bit more verbose, but should work as you intended:

const documents = [
  {
    id: 1,
    text: "Some example text",
    price: "123.21 €"
  },
  // more documents…
]

const miniSearch = new MiniSearch({
  fields: ['text', 'price']
})

const searchQuery = "some search query"

miniSearch.search({
  queries: [
    { fields: ['text'], prefix: true, queries: [searchQuery] },
    { fields: ['price'], prefix: false, queries: [searchQuery] }
  ]
})
Thomas-1985 commented 1 year ago

Thanks a lot, this worked! :)