Searching shouldn’t be so hard
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:
For simplicity’s sake, I’ll assume that you have the following class:
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:
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:
That would now find results for “Rama Thai”, right? But what about “Mr Korean” ? Consider a user who have 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:
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 merge all of those details together and arrange them in such a way that the following query can be done:
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 kind of features can dramatically uplift your applications’ usability and attractiveness to users. “This sites gets me”.
Comments
This might be a bit off topic but I'm curious (as I never had the need for this type of searching) what would be involved to do the same in a tradition RDBMS like SQL Server compared to RavenDB? Full-text searching enabled and configured?
Note: Not looking for any sort of solution. Just interested in another perspective and find this an interesting topic.
Stephen, I assume that you would need to manually construct the aggregated field, and then use the db full text searching. That tend to be manual process in most cases
What perfect timing. I'm doing something similar and wanted to use this code. What I take away is putting the fields to search into an array of strings. I was searching each individual fields.
I believe I found some typos though.
public Restaurant_Search()
select new Result
Indexes.Add(x => x.Query, FieldIndexing.Analyzed);
Guy, You are correct, the ctor was wrong.
However, the rest is accurate. This has to do with the various locations that the index is running. You can put
new Result
there, but then you'll have to make theQuery
property astring[]
, or maybeobject[]
, depending on what exactly you are indexing.The idea is that the index runs server side, where there are no types, and then on the client side, you use the
Result
class to access it. In effect, there are:Which aren't necessarily the same thing.
I still get an error with
Indexes.Add(x => x.Cuisine, FieldIndexing.Analyzed);
The error is Restaurant_Search.Result does not contain a definition for 'Cuisine'.I got it to work without a
select new Result
and I understand that part now, almost. The challenge is understanding what the server wants/needs vs. what the clients wants/needs.And yes you will see I have
Query = new []
Guy, Sorry, that should be
Query
, notCuisine
This sounds like a good use case for something like Algolia. Not 100% how they do it but they do full text fast and accurate.
Andrew, That is something external that you have to manage yourself This is directly inside the same transactional database
I just implemented this on the RavenDB 4.0 test site. One other thing I noticed while doing that is the property name
Address
is the same name as the Class. I changed it toStreetAddress
. When working with my own project I used the idea, but applied it to a different domain and that is why I did not find this until now.Restaurant Database
Guy, Thanks, I fixed the property names
Comment preview