Systenics Solutions Logo
  • Home start here
  • Solutions services we provide
  • Products products we build
  • About Us who we are
  • Contact Us request a quote
  • Jobs work for us
  • Blog our views

Blog

Home / Blog

Use Lucene.Net in for faster data search

  • by:
  • in:
  • tags: .NET, C-Sharp, Lucene
  • 0 Comments

Introduction

This tutorial explains how to use Lucene.Net to achieve faster search responses in ASP.NET or MVC or C# applications.

Why Lucene.Net?

All business or consumer applications require data search and it can be implemented using SQL LIKE clause or SQL Full-Text Search. But we found that it is much faster to search data when we use Lucene.Net library.

Lucene is a full-text search library which uses inverted index for search due to which it is able to achieve fast search responses. You can use Lucene.Net library to create indexes and search to retrieve the data which can be sorted by relevance or by a sort field.

“Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users. The Lucene search library is based on an inverted index.”

Read more about Lucene.Net from Apache Lucene.Net or Lucene.Net GitHub.

Let’s start with the coding :)

Setup C# Lucene Project

Before you start writing your first example using Lucene.Net library, you have to make sure that you have setup your Lucene environment properly.

Let’s start by creating a new project with name - “LuceneConsoleApplication”. Open VS and New Project -> Visual C# -> Windows -> Console Application.

Add "Lucene.Net" references using NuGet Package Manager in your project.

Add below key in App.config file. This is the path where we will store the Lucene indexes. It will create "LuceneIndexes" in bin directory. We can even pull the data from SQL Server database and create Lucence indexes. In this tutorial and sample given below, we have created a list using C# code.

                
    <add key="LuceneIndexStoragePath" value="LuceneIndexes" />
    

 

In code given below, the StartLuceneIndexCreateProcess() method will create Lucene indexes.

    
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                LuceneIndexer startIndexer = new LuceneIndexer();
                Console.WriteLine("Starting Lucene index creation process for search...\r\n");
                Console.WriteLine("Lucene index has been created from the following list:");
                // This method will create Lucene indexes according to your given list items.
                startIndexer.CreateLuceneIndexes();
                Console.WriteLine("");
                // You can check CFX and CFS file in folder "..\LuceneConsoleApplication\App_Data". 
                // Open the file in Notepad or any other text editor and you can see list of items.
                Console.WriteLine("Lucene Index creation successful!\r\n");
                GetSearchLucene getSearchLucene = new GetSearchLucene();
                Console.WriteLine("Enter a name to search:");
                // Get input string from user
                string inputParam = Console.ReadLine();
                List result = getSearchLucene.GetSearchLuceneText(inputParam);
                Console.WriteLine("");
                Console.WriteLine("You searched for:");
                if (result.Count > 0)
                {
                    foreach (var item in result)
                    {
                        Console.WriteLine(item.Actor);
                    }
                }
                else
                {
                    Console.WriteLine("Sorry! No matching records found.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }

File #1 - Program.cs – Main() method

 

 

Create Indexes for Search

Now, let’s add list of items to CreateDocument() method.

Directory represents the storage location of the indexes. Write your desired directory path in the App.config file. Here we will create our index of our list items. User given input will searched with "Actor" key field.

        private void StartLuceneIndexCreateProcess()
        {
            string luceneIndexStoragePath = @ConfigurationManager.AppSettings["LuceneIndexStoragePath"];
            bool folderExists = System.IO.Directory.Exists(luceneIndexStoragePath);
            if (!folderExists)
                System.IO.Directory.CreateDirectory(luceneIndexStoragePath);
            analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
            Lucene.Net.Store.Directory directory = Lucene.Net.Store.FSDirectory.Open(new System.IO.DirectoryInfo(luceneIndexStoragePath));
            writer = new Lucene.Net.Index.IndexWriter(directory, analyzer, true, Lucene.Net.Index.IndexWriter.MaxFieldLength.LIMITED);
            try
            {
                // We will populate below list to create Lucene index.
                List actorsList = new List();
                actorsList.Add("Johnny Depp");
                actorsList.Add("Robert Downey Jr.");
                actorsList.Add("Johnny Depp");
                actorsList.Add("Tom Cruise");
                actorsList.Add("Brad Pitt");
                actorsList.Add("Tom Hanks");
                actorsList.Add("Denzel Washington");
                actorsList.Add("Russell Crowe");
                actorsList.Add("Kate Winslet");
                actorsList.Add("Christian Bale");
                actorsList.Add("Hugh Jackman");
                actorsList.Add("Will Smith");
                actorsList.Add("Sean Connery");
                foreach (var item in actorsList)
                {
                    Console.WriteLine(item);
                    writer.AddDocument(CreateDocument(item.ToString()));
                }
            }
            catch
            {
                Lucene.Net.Index.IndexWriter.Unlock(directory);
                throw;
            }
            finally
            {
                writer.Optimize();
                analyzer.Close();
                writer.Dispose();
                analyzer.Dispose();
            }
        }
        private Lucene.Net.Documents.Document CreateDocument(string actorName)
        {
            try
            {
                Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
                doc.Add(new Lucene.Net.Documents.Field("actors", actorName, Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.ANALYZED));
                return doc;
            }
            catch
            {
                throw;
            }
        }

File #2 – LuceneIndexer.cs - Contains code to create Lucene indexes

 

Search

Provided input will pass to GetSearchLuceneText() method. GetLuceneIndexPath() method will get the path of stored Lucene index i.e "bin\Debug\LuceneIndexes" folder. Input given by user will search in "LuceneIndexes" folder using Search() method.

    public class GetSearchLucene
    {
        public List GetSearchLuceneText(string actorName)
        {
            LuceneSearcher searchIndex = new LuceneSearcher(GetLuceneIndexPath().FullName);
            List results = new List();
            if (actorName != string.Empty)
            {
                results = searchIndex.Search(actorName, "actors").ToList();
            }
            return results;
        }
        // Get directory path for Lucene index creation
        public DirectoryInfo GetLuceneIndexPath()
        {
            return new DirectoryInfo(ConfigurationManager.AppSettings["LuceneIndexStoragePath"]);
        }
    }

File #3 -  GetSearchLucene.cs - Contains code to invoke search on Lucene indexes

 

Search method

IndexSearcher class acts as a core component which searcher indexes created during indexing process. Lucene directory will point to location where indexes are to be stored. Initialize the QueryParser object created with a standard analyzer having version information and index name on which this query is to run.

       
        public List Search(string searchText, string searchField)
        {
            List output = new List();
            string searchQuery = string.Empty;
            try
            {
                if (string.IsNullOrEmpty(searchText.Trim()))
                {
                    throw new Exception("You forgot to enter something to search for...");
                }
                searchQuery = searchText;
            }
            catch
            {
                throw;
            }
            try
            {
                // Open the IndexReader with readOnly=true. 
                // This makes a big difference when multiple threads are sharing the same reader, 
                // as it removes certain sources of thread contention.
                searcher = new Lucene.Net.Search.IndexSearcher(_directory, true);
                analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
                output = (GetSearchResultByField(searchQuery, searchField, searcher, analyzer));
            }
            catch
            {
                throw;
            }
            finally
            {
                analyzer.Close();
                analyzer.Dispose();
                searcher.Dispose();
            }
            return output;
        }

File #4.1 – LuceneSearcher.cs - Contain code to search on Lucene indexes

 

Mapping With Lucene

User given input will be mapped with search field and user input search will be fetched from document object.

        private Lucene.Net.Search.Query ParseQuery(string searchQuery, Lucene.Net.QueryParsers.QueryParser parser)
        {
            Lucene.Net.Search.Query query;
            try
            {
                query = parser.Parse(searchQuery.ToLower().Trim() + "*");
            }
            catch (Lucene.Net.QueryParsers.ParseException)
            {
                query = parser.Parse(Lucene.Net.QueryParsers.QueryParser.Escape(searchQuery.Trim()));
                throw;
            }
            return query;
        }
        private IEnumerable MapLuceneDataToIDList(IEnumerable hits, Lucene.Net.Search.IndexSearcher searcher)
        {
            return hits.Select(hit => MapLuceneData(searcher.Doc(hit.Doc))).ToList();
        }
        // Mapping Lucene data
        private LuceneData MapLuceneData(Lucene.Net.Documents.Document doc)
        {
            return new LuceneData
            {
                Actor = (doc.Get("actors"))
            };
        }

File #4.2 – LuceneSearcher.cs - Contains code to prase and map Lucene search data

 

You can download our sample LuceneConsoleApplication project from GitHub.

Happy Coding :)

Share This Post:

About the Author

This post was written by on Sunday February 12, 2017.

comments powered by Disqus
< Older Newer >
All Categories
  • Programming
  • General
  • DevOps
Tags
  • .NET (9)
  • Ajax (1)
  • Android (3)
  • ASP.NET (1)
  • ASP.NET 4.5 (1)
  • ASP.NET 5 (1)
  • ASP.NET 6 (1)
  • asp.net core (1)
  • ASP.NET MVC (12)
  • AuctionWorx (2)
  • Bootstrap (4)
  • Build and Release (1)
  • CI (1)
  • ClickOnce (1)
  • ClientDependency (1)
  • Code Signing (1)
  • Continuous Integration (1)
  • C-Sharp (9)
  • devops (1)
  • ExpressJS (1)
  • Interview Process (1)
  • iOS (1)
  • Linux (1)
  • Lucene (1)
  • MVC (2)
  • NodeJS (1)
  • Phonegap (3)
  • Razor (4)
  • Salesforce (2)
  • Socket.IO (1)
  • SQL CE 3.5 SP2 (1)
  • SQL Server (1)
  • Sync (1)
  • Sync Framework v2.1 (1)
  • Umbraco 6 (6)
  • Umbraco 7 (4)
  • Visual Studio 2015 (1)
  • Visual Studio Online (1)
  • VMWare ESXI 6.0 (1)
  • WCF (1)
  • Windows (2)
  • WPF (2)

About Us

Systenics Solutions is a customized software development company. We specialize in building Cloud, Web, and Mobile based applications using the latest Cloud Technologies. Our fine-tuned agile processes help you smoothly progress from conceptualizing your ideas, building proto-types/wireframes to bringing your product to market, giving our clients complete visibility and control at all times. We strive to provide our global clients of various sizes with cost effective benefits of offshore development while providing expert technical services.


Microsoft Partner - Gold Cloud Platform

Contact Us

Systenics Solutions

The Affaires, Unit #F-1, 1st Floor, Plot #9, Sector - 17, Opp. Bhumiraj Costarica, Sanpada, Navi Mumbai - 400705, India

 

Telephone: +91-22-2781 0808

Email: info@systenics.com

Skype: saurabhn

Testimonials

"Coming from a non-technical background, Saurabh and his team at Systenics took my business idea and turned it into a fully functional application which surpassed my expectations! You can be sure with them that all your IT related concerns will be covered."

Shobhan, CEO - IITJobs Inc

"The ability Systenics showed in code signing and deploying my click once code in Microsoft visual was truly awesome. I interviewed and tested 6 different development companies and only one was actually able to get the job done - that was Systenics Solutions! Professional, courteous and reliable - I highly recommend them and am very happy and eager to continue growing our business relationship now and in the near future. Thank you Saurabh"

Andre Pierre

I contracted with Systenics about 6 months ago, in an effort to customize auction software for a new company I am launching in the US. The entire process was as smooth as could be. Their estimate for the project was reasonable, and very close to the final number. I would absolutely use this company again, and I have so much confidence in their ability to work with me, I even agreed to a support agreement with them long term. Their ability to communicate with me in the US was always very timely. They listened to my thoughts and ideas, and then suggested some changes, that made my software have even greater value. I cannot thank them enough, and would highly suggest their quality services to anyone. A completely satisfied customer!

Joe Lefebvre - Pharmabid, LLC

Systenics did a great job on our customization , they clearly understood the requirements and completed the task in a timely manner. They were very thorough in project discussions and made sure that we understood how the customization works and suggested improvements when required

Mike Singh - Dr. Liquidator

Copyright © 2012-2018 Systenics Solutions. All rights reserved.

BACK TO TOP