Match Partial Search Query With Spaces
Hi! Love this library and really enjoy using it for all my JS projects!
I'm trying to figure out the best way for fuzzysort to match a string if a search query has spaces. I think it's easiest to explain what I am trying to do with a few examples:
query = 'hello world';
fuzzysort.single(query, 'hello world'); //should return an exact match
fuzzysort.single(query, 'hello'); //right now it returns null, I want it to match since it's a partial match of the query
One option I have done so far is to split on ' ' which does properly match partial words but then highlight functionality is off since it's using different fuzzysort.single() queries.
One option I have done so far is to split on
' 'which does properly match partial words but then highlight functionality is off since it's using differentfuzzysort.single()queries.
this is the correct solution. not sure why your highlighting would be off. here's a function to merge the results of multiple searches
const go = (search, targets, options) => {
if(!Array.isArray(search)) return fuzzysort.go(search, targets, options)
return search
.filter((s,i) => search.indexOf(s) === i)
.flatMap(s => fuzzysort.go(s, targets, options).map(r => { return {...r} }))
.sort((a,b) => b.score-a.score)
.filter((result, i, results) => i === results.findIndex(r => r.target === result.target))
}
in your case use it like this
let search = 'hello world'
go([search, ...search.split(' ')], ['hello world']) // returns exact match
go([search, ...search.split(' ')], ['hello']) // returns partial match
Thanks so much for the quick response! I am trying to use the example you gave and it's not merging the results the way I expect. When calling the highlight function on the exact match, it only highlights the second word. The score is also -6 on hello world but 0 on hello which I wouldn't expect since the first one should be the higher score.
console.log("test start");
const go = (search, targets, options) => {
if(!Array.isArray(search)) return fuzzysort.go(search, targets, options)
return search
.filter((s,i) => search.indexOf(s) === i)
.flatMap(s => fuzzysort.go(s, targets, options).map(r => { return {...r} }))
.sort((a,b) => b.score-a.score)
.filter((result, i, results) => i === results.findIndex(r => r.target === result.target))
}
let search = 'hello world'
let r1 = go([search, ...search.split(' ')], ['hello world'], {}) // returns exact match
console.log(fuzzysort.highlight(r1[0])); // hello <b>world</b>
let r2 = go([search, ...search.split(' ')], ['hello'], {}) // returns partial match
console.log(fuzzysort.highlight(r2[0])); // <b>hello</b>
console.log("test end");
oops. you're right. there's 2 issues here.
- because of performance optimizations, the highlight information is being overwritten by following searches.
- because of the new way spaces behave in 2.0, "hello world" doesn't match against "hello world" with a perfect score anymore .-.
i removed the sort, and added a precomputed highlight field:
const go = (search, targets, options) => {
if(!Array.isArray(search)) return fuzzysort.go(search, targets, options)
return search
.filter((s,i) => search.indexOf(s) === i)
.flatMap(s => fuzzysort.go(s, targets, options).map(r => { return {...r, highlight:fuzzysort.highlight(r)} }))
.filter((result, i, results) => i === results.findIndex(r => r.target === result.target))
}
let search = 'hello world'
console.log(go([search, ...search.split(' ')], ['hello world'])[0].highlight)
console.log(go([search, ...search.split(' ')], ['hello'])[0].highlight)
This is great! Gives me a good jumping off point to accomplish what I am trying to do 😄
One more question! 🙈
Would you know why this is highlighting hello instead of hello my?
let test = 'hello my name';
console.log(go([test, ...test.split(' ')], ['hello my test']));
you're never searching for hello my, you'd need to generate more search permutations than a simple split
Right but would it be possible to combine the highlights? You search for hello and that highlights the first word. You then search for my and that highlights the second word. If you combine both you should see a highlight for hello my without needing to look for all the different permutations
that's possible, but a little complicated. this isn't a well supported use case. btw, what is your use case? why do you want this?