Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

autosuggest

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

autosuggest

  • 0.3.0
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Autosuggest

Generate autocomplete suggestions based on what your users search

:tangerine: Battle-tested at Instacart

Build Status

Installation

Add this line to your application’s Gemfile:

gem "autosuggest"

Getting Started

Prepare your data

Start with a hash of queries and their popularity, like the number of users who have searched it.

top_queries = {
  "bananas" => 353,
  "apples"  => 213,
  "oranges" => 140
}

With Searchjoy, you can do:

top_queries = Searchjoy::Search.group(:normalized_query)
  .having("COUNT(DISTINCT user_id) >= 5").distinct.count(:user_id)

Then pass them to Autosuggest.

autosuggest = Autosuggest::Generator.new(top_queries)
Filter duplicates

Stemming is used to detect duplicates like apple and apples.

Specify the stemming language (defaults to english) with:

autosuggest = Autosuggest::Generator.new(top_queries, language: "spanish")

The most popular query is preferred by default. To override this, use:

autosuggest.prefer ["apples"]

To fix false positives, use:

autosuggest.not_duplicates [["straws", "straus"]]
Filter misspellings

We tried open-source libraries like Aspell and Hunspell but quickly realized we needed to build a corpus specific to our application.

There are two ways to build the corpus, which can be used together.

  1. Add words
autosuggest.parse_words Product.pluck(:name)

Use the min option to only add words that appear multiple times.

  1. Add concepts
autosuggest.add_concept "brand", Brand.pluck(:name)
Filter words

Profanity is blocked by default. Add custom words with:

autosuggest.block_words ["boom"]
Generate suggestions

Generate suggestions with:

suggestions = autosuggest.suggestions
Save suggestions

Save suggestions in your database or another data store.

With Rails, you can generate a simple model with:

rails generate autosuggest:suggestions
rails db:migrate

And update suggestions with:

now = Time.now
records = suggestions.map { |s| s.slice(:query, :score).merge(updated_at: now) }
Autosuggest::Suggestion.transaction do
  Autosuggest::Suggestion.upsert_all(records, unique_by: :query)
  Autosuggest::Suggestion.where("updated_at < ?", now).delete_all
end

Leave out unique_by for MySQL, and use activerecord-import for upserts with Rails < 6.

Show suggestions

Use a JavaScript autocomplete library like typeahead.js to show suggestions in the UI.

If you only have a few thousand suggestions, it’s much faster to load them all at once instead of as a user types (eliminates network requests).

With Rails, you can load all suggestions with:

Autosuggest::Suggestion.order(score: :desc).pluck(:query)

And suggestions matching user input with:

input = params[:query]
Autosuggest::Suggestion
  .order(score: :desc)
  .where("query LIKE ?", "%#{Autosuggest::Suggestion.sanitize_sql_like(input.downcase)}%")
  .pluck(:query)

You can also cache suggestions for performance.

Rails.cache.fetch("suggestions", expires_in: 5.minutes) do
  Autosuggest::Suggestion.order(score: :desc).pluck(:query)
end
Additional considerations

You may want to have someone manually approve suggestions:

Autosuggest::Suggestion.where(status: "approved")

Or filter suggestions without results:

Autosuggest::Suggestion.find_each do |suggestion|
  suggestion.results_count = Product.search(suggestion.query, load: false).count
  suggestion.save! if suggestion.changed?
end

Autosuggest::Suggestion.where("results_count > 0")

You can add additional fields to your model/data store to accomplish this.

Example

top_queries = Searchjoy::Search.group(:normalized_query)
  .having("COUNT(DISTINCT user_id) >= 5").distinct.count(:user_id)
product_names = Product.pluck(:name)
brand_names = Brand.pluck(:name)

autosuggest = Autosuggest::Generator.new(top_queries)
autosuggest.parse_words product_names
autosuggest.add_concept "brand", brand_names
autosuggest.prefer brand_names
autosuggest.not_duplicates [["straws", "straus"]]
autosuggest.block_words ["boom"]

suggestions = autosuggest.suggestions

now = Time.now
records = suggestions.map { |s| s.slice(:query, :score).merge(updated_at: now) }
Autosuggest::Suggestion.transaction do
  Autosuggest::Suggestion.upsert_all(records, unique_by: :query)
  Autosuggest::Suggestion.where("updated_at < ?", now).delete_all
end

Upgrading

0.2.0

Suggestions are now filtered by default, and only the query and score are returned. Get all queries and fields with:

autosuggest.suggestions(filter: false)

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development:

git clone https://github.com/ankane/autosuggest.git
cd autosuggest
bundle install
bundle exec rake test

FAQs

Package last updated on 23 May 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc