krisk / Fuse

Lightweight fuzzy-search, in JavaScript
https://fusejs.io/
Apache License 2.0
18.05k stars 766 forks source link

Weighted values, not keys? #444

Closed tommedema closed 4 years ago

tommedema commented 4 years ago

We're looking to use Fuse to implement an email autocomplete component. A typical input might look like this:

  const data = [
    { email: 'frequent@host.tld', weight: 1 },
    { email: 'frequent@not.tld', weight: 0.5 },
  ]

Here frequent@host.tld has a higher weight because this email address is used more frequently than frequent@not.tld. If the user now searched for "frequent", the entry with the higher weight should appear above the entry with the lower weight.

Since the keys are the same, this is a weighted search on a value basis, rather than on a key basis. How would we achieve this with Fuse?

krisk commented 4 years ago

Looks like you’re looking for value-based boosting at query time. Since this isn’t supported out-of-the box (and I don’t have plans to include it), you could work around the issue by:

  1. Do the standard search
  2. Once you have all your results, for every returned item:
    • Get the weight for that value
    • Update the score to take into account the weight.
      • i.e., you could do score = score * ((1 - weight) || 1)
  3. Resort the list based on the new score

(Note: make sure you set includeMatches to true, that way if you have multiple matched entries per item, you’ll know exactly which key/value was matched)