Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Searching Shouldn't Be So Hard

DZone's Guide to

Searching Shouldn't Be So Hard

Implementing search into your UI? It doesn't have to be difficult for your user. Here are some things to consider when building a search capability for your users.

· Web Dev Zone
Free Resource

Never build auth again! Okta makes it simple to implement authentication, authorization, MFA and more in minutes. Try the free developer API today! 

The trigger for this post is a StackOverflow question that caught my eye.

Let us imagine that you have the following UI, and you need to implement the search function:

enter image description here

For simplicity’s sake, I’ll assume that you have the following class:

public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Cuisine { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }
    public Address Address { get; set; }
}

public class Address
{
public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public int Postcode { get; set; }

}

And we need to implement this search, we want users to be able to search by the restaurant name, or its location or its cuisine, or all of the above, for that matter. A query such as”Rama Thai” or “coffee 48th st” should all give us results.

One way of doing that is to do something like this:

session.Query<Restaurant>()
.Where(x=>
x.Name == userSearchString ||
x.Cuisine == userSearchString ||
x.Address.Street == userSearchString ||
x.Address.City == userSearchString 
)
.ToList();

Of course, that would only find stuff that matches directly. It will find “Rama” or “Thai”, but “Rama Thai” would confuse it. We can make it better, somewhat, but doing a bit of work on the client side and changing the query, like so:

var parts =  userSearchString.Split();
session.Query<Restaurant>()
.Where(x=>
x.Name.In(userSearchString) ||
x.Cuisine.In(userSearchString) ||
x.Address.Street.In(userSearchString) ||
x.Address.City.In(userSearchString)
)
.ToList();

That would now find results for “Rama Thai”, right? But what about “Mr Korean” ? Consider a user who has no clue about the restaurant name, let alone how to spell it, but just remember enough pertinent information “it was Korean food and had a Mr in its name, on Fancy Ave”.

You can spend a lot of time trying to cater for those needs. Or you can stop thinking about the data you search as the same shape of your results and use this index:

public class Restaurant_Search : AbstractIndexCreationTask<Restaurant, Restaurant_Search.Result>
{
      public class Result
      {
         public string Query;
      }

      public Restaurant_ByCuisine()
      {
          Map = restaurants => from restaurant in restaurants
                               select new
                               {
                                   Query = new []
                                   {
                                     restaurant.Cuisine, 
                                     restaurant.Address.Street,   
                                     restaurant.Address.City,  
                                     restaurant.Name
                                   }
                               };

          Indexes.Add(x => x.Cuisine, FieldIndexing.Analyzed); 
      }
}

Note that what we are doing here is picking from the restaurant document all the fields that we want to search on and plucking them into a single location, which we then mark as analyzed. This let RavenDB know that it is time to start cranking. It merges all of those details together and arranges them in such a way that the following query can be done:

 var matches = session.Query<Restaurant_Search.Result, Restaurant_Search>()
      .Search(x => x.Query, "Fancy Mr Korean")
      .OfType<Restaurant>()
      .ToList();

And now we don’t do a field by field comparison, instead, we’ll apply the same analysis rules that we applied at indexing time to the query, after which we’ll be able to search the index. And now we have sufficient information not just to find this a restaurant named “Fancy Mr Korean” (which to my knowledge doesn’t exist), but to find the appropriate Korean restaurant in the appropriate street, pretty much for free.

Those kinds of features can dramatically uplift your applications’ usability and attractiveness to users. “This sites gets me”.

Launch your application faster with Okta’s user management API. Register today for the free forever developer edition!

Topics:
search ,web dev ,user experience

Published at DZone with permission of Oren Eini, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}