New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

plain_search

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

plain_search

  • 0.1.0
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

PlainSearch

PlainSearch is a dead-simple, scored search plugin for single ActiveRecord models. Suited for small projects with little needs for scalability and a reserved attitude towards technical debt (i.e. ElasticSearch, Solr, ...).

Quick Start

Setup

Add the Gem to your Gemfile:

gem 'plain_search'

Run bundle install to install it.

You'll need a table for caching the search terms. Run the generator for a new migration:

rails g migration CreateSearchTerms

Put this into the migration file:

class CreateSearchTerms < ActiveRecord::Migration
    def change
        create_table :search_terms do |t|
            t.string :term, index: true
            t.string :source, index: true
            t.belongs_to :findable, polymorphic: true
        end
    end
end

Apply the changes by running rake db:migrate.

At the moment the Gem doesn't provide the AR model for search terms (feel free to add it - pull requests appreciated).

So you'll have to add it to you model. Create app/model/search_term.rb with this content:

class SearchTerm < ActiveRecord::Base
  belongs_to :findable, polymorphic: true
end

Having, for instance, a model Employee which has the attributes first_name, last_name, profession and address, you can enable ranked searches like so:

class Employee < ActiveRecord::Base
    searchable_by id: 100, first_name: 10, last_name: 10, profession: 5, address: 1
    # ...
end

searchable_by receives a hash as only argument. Its keys determine the attributes to search. The hash's values determine the value contributed to the rank for a single match. In short: The higher the value, the higher the rank. See #Ranking for details.

Performing searches

Now, with all the setup done, performing a search is pretty straight-forward:

matches = Employee.search('susi sorglos 33602 hauptstrasse developer')

matches contains a list of Employees, ordered by the search score, which is also available as an attribute (e.q. matches[0].score).

Rebuilding search terms

In the background, whenever you create or update a model on which searchable_by was called, the searchable fields' contents will be cached in the search_terms table. This means pre-existent records won't appear in the search results because they have never hit the respective post-save callback. You'll have to rebuild the cache for this models manually using #rebuild_search_terms_for_all like so:

Employee.rebuild_search_terms_for_all

Performing updates without caching search terms

Let's say you have a scenario which performs a lot of updates to a specific model. Every insertion or update would result in SearchTerms being build for the respective record. This can be very time consuming (keep in mind that PlainSearch is not a high performance beast, but a mere solution for prototyping).

To circumvent this you can call the insertions/updates inside a block passed to #without_search_term_updates. Which simply suppresses the after_save callback which normally builds SearchTerms.

An example:

Employee.without_search_term_updates do 
 Employee.update_all({some_non_searchable_attribute: 42})
end

Therefore changes to searchable attributes within won't be reflected in the search results. So you should make sure that you either rebuild the search terms afterwards (e.q. using ActiveJob) or make sure no searchable attributes have been touched in the operation.

Alternatively you could set Model#auto_update_search_terms to true/false, which is basically what #without_search_term_updates does, but in a less error-prone manner.

Search term delimiter

Values of searchable attributes are split into search terms using a regular expression. This is /[^\w\u00C0-\u00ff]/ by default. You can adjust it to fit your specific needs:

class Employee < ActiveRecord::Base
    searchable_by # ...
    search_terms_delimiter = /[\-.]/
    # ...
end

Ranking

Plain search facilitates a very simple ranking algorithm. Every attribute considered for search has a score assigned to it. This is the score of a single match. The total score of a search result is the sum of the score of all matches.

Here's an example: If we had an Employee with first_name being "Susi" and her profession being "Web developer", then (in the scenario above), a query for "susi web" would result in a total score of 15 for this record. That is 10 for the matching first name and 5 for the matching profession.

License

See MIT-LICENSE

FAQs

Package last updated on 08 Nov 2015

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