fuzzysort icon indicating copy to clipboard operation
fuzzysort copied to clipboard

Using a key whose value is an array

Open n8sb opened this issue 2 years ago • 4 comments

I have an object with a key called "tags" whose value is an array of tags:

const allResources = {name: foo, tags:["123","abc"]};
const searchTerm = e.target.value;
const results = fuzzysort.go(searchTerm, allResources, { key: "tags" }); // "tags" is an array
console.log(results); // [total: 0]

I am able to search an array directly, but when the array is within an object, the return value is "[total: 0]".

Is there a way to make this work?

n8sb avatar Jul 12 '22 21:07 n8sb

no. you should make a list of all tags, search those, then find resources with matching tags.

that said, if performance doesn't matter you could generate a temporary searchable list before every search.

var allResources = [
  {name:'foo', tags:["123","abc"]},
]

var targets = allResources.flatMap(resource => {
  return resource.tags.map(tag => ({resource, tag}))
})

var results = fuzzysort.go('abc', targets, { key: 'tag' })
console.log(results[0].obj.resource)

farzher avatar Jul 13 '22 12:07 farzher

Excellent. Thanks for the help and the package!

n8sb avatar Jul 13 '22 19:07 n8sb

I found another solution: You can add a getter that groups everything that should be searchable into a single string:

const allResources = [
  { name: 'foo', tags: ['123', 'abc'] }
]

const searchableResources = allResources.map((item) => {
  return {
    ...item,
    get searchString() {
      // This creates the string "foo 123 abc"
      return `${item.name} ${item.tags.join(' ')}`
    }
})

fuzzysort.go('abc', searchableResources, { key: 'searchString' })

But honestly, what I'd find really handy is a new option that does what get searchString does. Something like this:

fuzzysort.go('abc', allResources, {
  filterValue(item) {
    return `${item.name} ${item.tags.join(' ')}`
  }
})

That would make the library more flexible. And in TS it wouldn't be necessary to introduce a new type for typeof allResources & { readonly searchString: string }.

alinnert avatar Nov 14 '22 11:11 alinnert

But honestly, what I'd find really handy is a new option that does what get searchString does. Something like this:

i'd rather not have more features if they're not necessary. your solution seems pretty good. i often just add a search key to my objects, although this does mutate the objects

const allResources = [{name: 'foo', tags: ['123', 'abc']}]
allResources.forEach(it => it.key = `${it.name} ${it.tags.join(' ')}`)
fuzzysort.go('abc', allResources, {key: 'key'})

your filterValue does seem quite simple and useful though 🤔

farzher avatar Apr 05 '24 09:04 farzher