Inside Wade, a 1kb search library
blog.kabir.ml
blog.kabir.ml
https://github.com/pieroxy/lz-string/pull/98
https://github.com/bvaughn/js-search/issues/42
The short version is: replace those single-char strings with the result of `charCodeAt()`, and then use `charCodeAt()` during search too. The reason is that integer key lookup is much faster than string key lookup:
https://stackoverflow.com/questions/10639488/faster-to-acces...
It's important that all of your keys are integers though, so the trick is to actually store/look up `charCodeAt()+1`, and then store the indices at key 0.
If you feel like taking a risk, you can make a slightly more complicated data structure where you replace the object with an array and do a linear search:
https://jsfiddle.net/vanderZwan/ccfxv4sg/1/
For most data this is the fastest, because the array will only be a handful of characters (except at the root). However, in certain special cases (specifically, if you have a lot of unique characters at the root) it becomes prohibitively slow.
I'm also interested in _why_ that is quicker though, aren't all object keys converted to strings anyway?
Hashing an integer or double can be much simpler than hashing a string, and like the other comment said: for small enough keys you might even get away with using an array.
edit: to give another example, the spec also says all number are doubles, and yet all JS modern engines use optimisations in places where it can guarantee a value is a 32-bit integer; in some cases adding `|0` (a forced truncation by bitmask-or zero) as a compiler hint can speed up code.
edit2: this is also part of why you want your objects to be as type-stable as possible (it also makes code less bug-prone that way because easier to reason about). This includes the shape of objects. See these slides from 2011:
https://www.slideshare.net/newmovie/know-yourengines-velocit...
Also, if the library removes stop words, does that mean its limited in which languages it supports? I'm assuming only English stop words are filtered
Not being critical here, just genuinely curious and don't have time to look through the code ATM
Switching to a trie-like structure that compresses prefixes and suffixes can lead to significant savings. Building the structure can be a bit more burdensome, so there is a trade off there. There is a paper describing the approach [2] and, if you're interested, my JavaScript implementation [3][4].
[2] http://www.aclweb.org/anthology/J00-1002.pdf
[3] https://github.com/olivernn/lunr.js/blob/master/lib/token_se...
[4] https://github.com/olivernn/lunr.js/blob/master/lib/token_se...
The stop words that are being removed can be configured via `Wade.config.stopWords`, which is an array of stop words that Wade will remove.
Good thinking on making them configurable!
[1, 1]
Is that supposed to be [0, 1]? If not, how does that correlate to ["Hey", "Hello"]?I'll add a note in the article.
Running the following doesn't seem to work for me:
var Wade = require('wade');
var search = Wade(['Hey', 'Hello']);
search('he'); // returns [] [1, 1]
The item at index 0 is 1. This means that the item in index 0 of the data ("Hey") has a score of 1. The item at index 1 is 1, meaning that the item at index 1 of the data ("Hello") has a score of 1.Edit: Your example with Wade isn't working because it ignores the first item in the query ("he") as it is a stop word. Searching for "h" will return both.
I'm still curious about using it. The GitHub example [1] works as described, but I can't get a result from the 'he' example. Is it saying no match was found by returning an empty array?
EDIT: Okay, saw your edit. Might be nice to use an example that's not a stopword. ;) Nice work on the library and the blog post.
PS: Am I the only one who thinks it is quite strange that "search", being one of the pillars of CS, has so few open-source libraries dedicated to it?
I totally agree, search is an extremely interesting topic and I learned a lot writing Wade. I'd definitely recommend people to learn more about how this kind of stuff works.
You can easily configure the stop words that Wade removes by editing `Wade.config.stopWords`.