Auto-complete using Elastic as the search engine

Elastic is a search engine built on top of Lucene. We build Auto-complete capability with Elastic.

Setting up Elastic

Download the zip file from Elastic site. Extract the zip file to a suitable folder. From the bin folder, run service.bat install. In the service manager, adjust the settings for the service. If you encounter Java errors, install Java runtime (8) from Oracle website. And finally, set the JAVA_HOME environment variable to point to JVM location.

Auto-complete UI

Next, we convert a Textbox into an auto-complete widget. Please refer to an earlier post: Autocomplete textbox using jQuery. It is time to build the server API to fetch data from Elastic Search.

Fetching data from Elastic

We need two settings to create the client: Server URL and Default index. Using the Search method in the client, we get the search results. For this example, search all the localities in the index. We use a wild-card search for the auto-complete. Finally, we iterate through the documents returned as search results and extract the relevant information.

public List<string> GetLocalities(string query)
{
    var node = new Uri("http://localhost:9200");

    var settings = new ConnectionSettings(
        node,
        defaultIndex: "my-application"
    );

    var client = new ElasticClient(settings);
    query = string.Format("*{0}*", query.ToLower());
    var searchResults = client.Search<LocalityDocument>(s => 
                            s.From(0)
                            .Size(100)
                            .Query(q =>
                                q.Wildcard(wqd => 
                                    wqd.OnField("name")
                                        .Value(query)
                                              )));

    return searchResults.Documents
                        .Select(d => d.Name)
                        .ToList();
}

Usually, the Elastic server is hosted at 9200. Data is organized as indexes. Within an index, there are multiple document types. For our example, localities are retrieved from the my-application index as a localitydocument type.

Indexing data to Elastic

The indexing job is a background task. It usually happens periodically. If there is a new document or if there is an update to an existing document, we index the document. Indexing prepares the document for reverse lookup or search. For this example, we index localities data from the database.

static void CreateLocalityIndex()
{
    using (var context = new DoctorPlus.Data.DoctorPlusContext())
    {
        var node = new Uri("http://localhost:9200");

        var settings = new ConnectionSettings(
            node,
            defaultIndex: "my-application"
        );

        var client = new ElasticClient(settings);

        var localities = context.Localities.ToList();

        foreach (var locality in localities)
        {
            var document = new LocalityDocument();
            document.Name = locality;
            client.Index(document);
            Console.WriteLine("Indexed {0}", document.Name);
        }
    }
}

We take localities from the database table. Use the settings to create an Elastic client. Pass the localities one-by-one to the Index method of the client. Indexing is a background process. It is usually a console application triggered from a scheduled task.

Related Posts

Leave a Reply

Your email address will not be published.