LunrCore, a lightweight search library for .NET
I'm pretty much convinced almost all applications need search. No matter what you're building, you'll likely handle data, and no matter how well you organize it, a good text search is often the fastest way for your users to find what they're looking for. As such, search should be a commodity, a feature that should be as easy as possible to integrate. I'm so convinced of that in fact that my day job is on Azure Cognitive Search, a Microsoft product that provides search as a service and makes indexing smart by adding a customizable pipeline of AI and machine learning enrichments.
A month ago, I saw this tweet:
The .NET library ecosystem is sometimes so unequipped. Every 5 years, I'm looking for a .NET library that could build a search index (inverted index, with stems, fuzzy search...etc.) that I could plug into a JS frontend library (e.g lunr.js), and it's still the same no lib's land
— Alexandre Mutel (@xoofx) June 24, 2020
Being a user of lunr.js myself (I used it as the search engine in my Node CMS project, Decent CMS), I agreed totally, and felt I had to do something. Of course, .NET has Lucene.NET, a port of Java's Lucene, and that's a fantastic library. We've been using it forever in Orchard, and it's a high-performance and mature project. It is however not that simple and it can in some situations lack flexibility. It's what your choice should be if you're building anything at scale, but if all you're trying to do is to plug search into your app with minimal headache and a very gentle learning curve, now you have LunrCore as an option...
LunrCore is a direct port of lunr.js. If you don't know it, lunr.js is a very nice JavaScript library that implements a simple search engine with a focus on simplicity. I really love it because it hits that sweet spot of commodity that I was talking about at the beginning of this post. Easy to integrate, easy to use, and still has almost all the features you'd expect:
- Index anything: just feed it a dictionary of strings to objects
- Stemmers
- Fuzzy search with edit distance and wildcards
- Boost
- Term presence or absence
- Scoring
- Stop words
- Search over fields or the entire document
- Pluggable indexing and search pipelines
Creating an index is as simple as this:
Then, searching it can be done through expressive search query strings or through an object model of combinable clauses.
Being a port of an existing JavaScript library, we also have an additional trick up our sleeves: an index can be prepared on the server, then sent down into the browser for super-fast client-side searches. The JSON that LunrCore produces when serializing an index can be consumed by the original lunr.js library. I think that is pretty cool if I may say so myself.
The library is of course open source under the MIT license, which means everybody should be able to use it to build commercial and non-commercial applications with no strings attached. It has no runtime dependency beyond the SDK, BCL AsyncInterfaces and System.Text.Json, making it even more of a no-brainer to integrate anywhere. I'd love to hear what you think and what you built with it, so don't hesitate to drop me a note (or even contribute something on GitHub).
Package: https://www.nuget.org/packages/LunrCore
Repository: https://github.com/bleroy/lunr-core
The original JavaScript library: https://lunrjs.com/guides/getting_started.html