krisk / Fuse

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

Is there any way to just look thru all the nested string without specify the keys? #563

Closed sooxt98 closed 2 years ago

sooxt98 commented 3 years ago

@krisk Instead of specify the keys, i wish there's a way to include everything into the search with *

const fuse = new Fuse(books, {
  keys: ['title', 'author.firstName']
})
const fuse = new Fuse(books, {
  keys: ['*']
})

https://github.com/krisk/Fuse/issues/546

cschweda commented 2 years ago

+1

Interested in this, too (for a smaller index, at least).

I assume performance is the issue here.

JordanMalan commented 2 years ago

While this could be useful, I would guess the results might differ from the users expectations...

Also, when initially defining the keys array, you'll need to provide an object to grab the searchable keys from -- you could try to pass the first entry in your array but if any of it's values are null where on other entries it might be a string, the searchable keys array will be missing that key since null is not searchable.

You could otherwise traverse each object at every key for each row when searching but that is as inefficient as it gets...

But heck I wanted to try it anyway, benchmark shows about 0.09ms for an array of this size I tried to optimize as much as possible, surprisingly setting a variable for typeof is faster than checking typeof a few times for some reason...

let object = {
    surface0: 'someValue',            // Valid
    surface1: {
        deeper0: "deeperValue",       // Valid
        deeper1: {
            deepest0: "deepestValue", // Valid
            deepest1: () => {},       // Invalid, not searchable
        },
        deeper2: false,               // Invalid, not searchable
    },
    surface2: {},                     // Valid but empty, not searchable
}

let keyCollection = [];

const pathFinder = (object, path = '') => {
    for (const property in object) {
        if (!object.hasOwnProperty(property)) continue;

        const type = typeof object[property];

        if (type === 'object') {
            pathFinder(object[property], `${path}${property}.`)
        } else if (type === 'string' || type === 'number') {
            keyCollection.push(path + property);
        }
    }
}

pathFinder(object)

console.log(keyCollection)

with a result of

[
    "surface0",
    "surface1.deeper0",
    "surface1.deeper1.deepest0"
]

But again if surface1.deeper0 had been null on this particular object, it wouldn't be searchable on any other objects

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days