The Tipter Blog

Tipter Logo

Autocomplete With Elasticsearch and Tire

| Comments

We’ve recently seen a need to introduce an autocomplete feature to Tipter. Tipter allows its users to search for Trips (a.k.a Travel Blogs) and Tips (the building blocks of Trips). I’ve spent couple of days on this feature, integrating multiple resources until I got the desired result.

This list of resources includes: this great blog post, which refers to an excellent Stack Overflow answer, and this issue on github which explains how to use multifield in Tire. It also includes this blog post which I only found at later stages, definitely could have saved me some time. And of course Elasticsearch guide, Tire documentation, and Railscast.

Let’s start by looking at some code. I’ve listed the relevant code snippets of our trip model. Each trip has_many countries which has_one sovereign model that hold the country’s name. Our target (for this post at least…) is to be able to perform autocomplete on the country name, and offer the user relevant travel blogs that include that country.

class Trip < ActiveRecord::Base
  has_many :countries, dependent: :destroy

  def countries_names
    sovereign_names = self.countries.map { |c| c.sovereign.nil? ? "" : c.sovereign.name }.join(", ")
    sovereign_names
  end


  include Tire::Model::Search
  include Tire::Model::Callbacks

  settings :analysis => { 
             :filter => {
               :trip_ngram  => {
                 "type"     => "edgeNGram",
                 "max_gram" => 15,
                 "min_gram" => 2 }
             },
             :analyzer => {
               :index_ngram_analyzer => {
                 "type" => "custom",
                 "tokenizer" => "standard",
                 "filter" => [ "standard", "lowercase", "trip_ngram" ] 
               }, 
               :search_ngram_analyzer => {
                 "type" => "custom",
                 "tokenizer" => "standard",
                 "filter" => [ "standard", "lowercase"] 
               }, 
             }     
          } 


  mapping do 
   indexes :countries_names, :type => 'multi_field', :fields => {
      :countries_names => { :type => "string"},
      :"countries_names.autocomplete" => { :search_analyzer => "search_ngram_analyzer", :index_analyzer => "index_ngram_analyzer", :type => "string"}
   }
  end

  def to_indexed_json 
    to_json(methods: [:countries_names])
  end

  def self.regular_search(params) 
    tire.search(load: true) do
       query {string 'countries_names:' + params }
    end
  end


  def self.autocomplete(params) 
    tire.search(load: true) do
       query {string 'countries_names.autocomplete:' + params }
    end
  end

So, for a start we’ll index the countries_names using the mapping block code. We will use the Elasticsearch multi_field type to define “regular” countries_names search, and autocomplete one. This will allow us to declare two different methods able to be used based on our needs. For the countries_names:autocomplete variant, we declare two types of analyzers :search_analyzer and :index_analyzer.

A great overview of analyzers’ structure and how they work in Elasticsearch can be found here, and I don’t want to repeat that (and probably introduce errors… :-) ). However, some of the modifications I did were to use Edge NGram token filter so that n-grams will only be generated from the beginning of the word.

In addition I used different filters for search and indexing where the search filter doesn’t use the Edge NGram filter.

My initial version of the mapping used a single analyzer:

 mapping do 
   indexes :countries_names, :type => 'multi_field', :fields => {
      :countries_names => { :type => "string"},
      :"countries_names.autocomplete" => { :analyzer => "index_ngram_analyzer", :type => "string"}
   }
 end

While playing with several search queries on the console, I ran this query:

1.9.3-p327 :159 > Trip.autocomplete("mar").map { |t| t.countries_names }
 ....
 => ["Malaysia", "Malaysia"] 

The reason it found Malaysia is because of the index containing the following tokens:

[ma], [mal], [mala], [malay], [malays], [malaysi], [malaysia]

Notice I used min_gram of two in order to reduces false positives. Using the same token filter, the search query translates to:

[ma], [mar]

So there’s a match on the “ma”. This can be avoided by using different search analyzer as in the first code snippet. Running the same query gets the expected result:

1.9.3-p327 :163 > Trip.autocomplete("mar").map { |t| t.countries_names }
 => [] 

1.9.3-p327 :164 > Trip.autocomplete("ma").map { |t| t.countries_names }
 ...
 => ["Malaysia", "Malaysia"] 

1.9.3-p327 :167 > Trip.regular_search("ma").map { |t| t.countries_names }
=> [] 

There you go. I hope this will save some of you the time I spent on wiring everything together.

Travel Blogging Made Simpler With Tipter’s Blogging Interface

| Comments

images

Tipter’s blogging interface is one of the features we like most about the app, and we want to tell you what makes it so special. You are probably familiar with today’s popular blogging systems. Many of them are built on WordPress or a similar software. We have no problem with WordPress, but we believe that it has some flaws that hurt the functionality of your blog. For instance, we aren’t a fan of the “Preview” button. We believe that, when you edit your blog, you should be able to see the content change in real time. Why should you have to guess how your blog is going to look before you publish it? Why should you have to troubleshoot issues, because you can’t edit your page and see the final product at the same time?

We don’t know the answer to these questions, so we decided to simplify the process for you.

With Tipter, you don’t have to guess. Your text will look exactly as it did on the edit screen – mainly because you edit and publish in the same window. Just open a new tip, write a recommendation or share a story, and click outside the tip’s window. Tipter will save your text automatically, and it will look exactly as it did when editing. Want to add, change, or delete something? No problem at all. Just click on the tip itself and the edit bar will appear on the top of the window. Edit to your heart’s desire, click outside the window, and your tip is automatically updated.

And of course, you can add a picture with the photo button use bold, italic or underline fonts, make a list, align the text left, right, or to the middle, and use any of the other features on the edit bar. You can also choose a subject for the tip – food, sightseeing, camping, nightlife, and many other options.

Choosing a subject for your tip will help other users look for it and help you get some Karma on the site’s rating system. But, that’s a matter for the next post on Tipter’s blog.

Does the World Really Need Another Travel Web App?

| Comments

images

We think so! Have you ever begun planning a trip and felt helpless and overwhelmed by all of the information on the internet? Did you wish you could just get advice from people you knew you could trust? We always feel this way while planning, which is why we came up with a solution: Tipter.

There are so many constraints involved when planning a trip: time, budget, season, age of your traveling companions, and countless others. Planning always takes time, can often be painful, and normally results in compromises and disappointment unless you’ve got unlimited budget, all the time in the world, and you are travelling with your identical twin. As for rest of us, we could use a little help.

You can always buy a travel guide, like in the good old days before the internet. You can utilize search engines and hope that you are asking the right questions to get the best information. But will you really figure out where to go when you travel to the south of France for three weeks, or what to do with two kids in Thailand? Probably not.

By analyzing our travel planning experience, we believe we have pinpointed the problem. Most online sources are focused on the specifics: flights, hotels, and restaurants. However, when you are starting to plan a trip, you are looking for information about the big picture. Finding a hotel or a good restaurant is the easy part. Finding the best route to take, most scenic viewpoint to look at, and the best time of day to find the shortest line at a landmark, however, is much harder. What you need is the combined wisdom of other travelers like you, who have been there and done that, and can tell you all about it.

How does Tipter help you solve this problem?

Tipter is a sophisticated social network of travelers like you. They share their experience, traveling tips, and itineraries. Tipter contains information from people who have visited where you want to go and therefore have gained the invaluable experience that can help you plan your trip. Their information can help you know where to go, what to pack, when to go, and how much time to allot for each location. You will be able to find great local restaurants, viewpoints, places to hang out, and much more. You will be able to sort through information and figure out where you want to spend your time, and where you don’t want to waste it. Tipter takes the tedious and time consuming process of trip planning and turns it into a fun, easy, and social experience.

When you return from your trip, you come back with great memories, tips, and recommendations. Tipter makes sharing this experience easier than ever. While on the road, you can blog your trip so that you can let people know what you are doing anywhere in the world. When you return from your trip, you can share the “inside knowledge” that you have gained with friends and family, the people that helped you plan the trip, and the whole world! Your tips will set in motion a cycle – others will use your information to plan their own trips, then they will give their own insight. The final product is an up-to-date, informative, and trust-worthy travel guide for the 21st century.

So yes, we do think the world needs another travel web app, because the right one just isn’t out there… yet. Currently, your options are limited to too much information from people you can’t trust, too many advertisements, and not enough information tailored to your needs. We have devoted the last year to building and improving Tipter, so that it can fulfill your needs. Today, we are ecstatic to let you know that our idea has become a reality. We still have a long way to go and have many ideas we have yet to implement for Tipter, but we’ll get there with your help. We have invested a lot of thinking into this application and are confident that we can solve the problems that come with planning a trip, for ourselves and for you. Come aboard and give Tipter a go, because it was made with you in mind.