Searchlogic released!

September 1st, 2008

Searchlogic's inspiration comes right from ActiveRecord. ActiveRecord lets you create objects that represent a record in the database, so why can't you create objects that represent searching the database? Now you can! It's searching, ordering, and pagination all in one.

Enough said, let me show you some of my favorite features. If you are still interested you can just jump over to the searchlogic github page for a more detailed explanation.

For the following examples lets assume these relationships: User => Orders => LineItems

Simple Searching Example

User.all(
  :conditions => {
    :first_name_contains => "Ben",          # first_name like '%Ben%'
    :email_ends_with => "binarylogic.com"   # email like '%binarylogic.com'
  },
  :per_page => 20,                      # limit 20
  :page => 3,                           # offset 40, which starts us on page 3
  :order_as => "ASC",
  :order_by => {:user_group => :name}   # order user_groups.name ASC
)

same as above, but object based

search = User.new_search
search.conditions.first_name_contains = "Ben"
search.conditions.email_ends_with = "binarylogic.com"
search.per_page = 20
search.page = 3
search.order_as = "ASC"
search.order_by = {:user_group => :name}
search.all

In both examples, instead of using the "all" method you could use any search method: first, find(:all), find(:first), count, sum, average, etc, just like ActiveRecord.

The beauty of searchlogic, integration with rails

Using Searchlogic in rails is the best part, because rails has all kinds of nifty methods to make dealing with ActiveRecord objects quick and easy, especially with forms. So let’s take advantage of them! That’s the idea behind this plugin. Searchlogic is searching, ordering, and pagination all rolled into one simple plugin. Take all of that pagination and searching cruft out of your models and let Searchlogic handle it. Check it out:

# app/controllers/users_controller.rb
def index
    @search = User.new_search(params[:search])
    @users, @users_count = @search.all, @search.count
end

Now your view.

# app/views/users/index.html.haml
- form_for @search do |f|
 - f.fields_for @search.conditions do |users|
  = users.text_field :first_name_contains
  = users.calendar_date_select :created_after # nice rails plugin for replacing date_select
  - users.fields_for users.object.orders do |orders|
    = orders.select :total_gt, (1..100)
  = f.submit "Search"

- if @users_count > 0
  %table
    %tr
      %th= order_by_link :account => :name
      %th= order_by_link :first_name
      %th= order_by_link :last_name
      %th= order_by_link :email
    - @users.each do |user|
      %tr
        %td= user.first_name
        %td= user.last_name
        %td= user.email

  Per page:
  = per_page_select
  Page:
  = page_select
- else
  No users returned

Things to notice

  1. Passing a search object right into form_for and fields_for
  2. The built in conditions for each column and how you can traverse the relationships and set conditions on them
  3. The order_by_link helper
  4. The page_select and per_page_select helpers
  5. All of your search logic is in 1 spot: your view. Nice and DRY.

See my tutorial on this example

Nifty methods for searching trees

Just like the conditions you automatically get with each column. You automatically get conditions for searching tree data structures, if you're model is a tree data structure.

# User is a tree data structure.
conditions = User.new_conditions
conditions.child_of = User.roots.first                  # Finds all children
conditions.sibling_of = User.first                      # Finds siblings
conditions.descendant_of = User.roots.first             # Finds all children, grandchildren, etc
conditions.inclusive_descendant_of = User.roots.first   # Includes root + children, grandchildren, etc.

Any of these conditions can accept a User object or a User id.

Get Started

Check out the GitHub repository to get started:

http://github.com/binarylogic/searchlogic/

Or a tutorial I posted on using Searchlogic in rails:

http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchlogic

17 Responses to “Searchlogic released!”

  1. September 10th, 2008 at 03:46 PM Stéphane Akkaoui Says

    Thanks for this ! It sounds beautifull : I’m raring to try it in a real case application !

    There is a typo on the users_controler sample code : there is a missing closing square bracket on line 3, ending the params selection.

  2. September 11th, 2008 at 03:40 AM Ben Johnson Says

    Good find! I fixed the typo. Let me know how using it goes. I love hearing feedback and am always looking to improve this.

  3. September 11th, 2008 at 09:31 AM mollo Says

    Thanks Ben for sharing this nice plugin!

  4. September 12th, 2008 at 05:17 AM Robert Says

    Thanks – this is indeed a very promising plugin.

  5. September 12th, 2008 at 06:07 AM Tjerk Says

    Too bad this is all too slow, you want to compile your queries…., but that is a inherent problem of activerecord.

  6. September 12th, 2008 at 10:03 AM Alex Gregianin Says

    I havent tested anything yet,but the idea sounds promising!I’m only worried about speed,as the guy above said this is not going as fast as it is supposed to be!I’m gonna do some benchmarks and comment here!

    Congratulations for the great work!

  7. September 12th, 2008 at 01:00 PM Ben Johnson Says

    Thanks for the comments. Tjerk, I agree, but I am not trying to replace ActiveRecord, I am building on top of it. I leverage it for anything I can and try not to “recreate the wheel”. I’m trying to keep this as simple and clean as possible. Alex, I did some benchmarks and they were positive. Since then I have made some minor changes, I will run some benchmarks and post my results, probably in the readme. Thanks for the feedback.

  8. September 12th, 2008 at 06:52 PM Ben Johnson Says

    I posted my benchmarking file along with the results on pastie.org. You can check it out here: http://pastie.org/271935. There are still some other things I can do to improve performance, but this definitely should not slow down your application. I plan to work on it more in the next few days. Thanks!

  9. September 14th, 2008 at 11:04 AM Oleg Says

    This plugin looks very promising. I’m tired of rolling half-assed searching/ordering code for every project. Thanks!

  10. September 25th, 2008 at 01:10 AM piter Says

    Hello,

    Looks great. What about will_paginate? Can I use it as always?

  11. September 26th, 2008 at 11:23 AM Cameron Says

    Very useful, was about to have to roll my own code doing exactly this, nice timesaver!

  12. October 11th, 2008 at 07:39 PM zvgeywag Says

    nvytlziw http://toragvcq.com bjwukduc nayyfrpm ypmkjwhk

  13. October 12th, 2008 at 04:31 AM ff Says

    i try your example and when i click on “search” i got this error: undefined method `nil_class=’ for #<userconditions>

    what the metter?

  14. October 28th, 2008 at 11:01 PM Ben Johnson Says

    FF, I am not sure. I would need a lot more information on this. Please go to lighthouse and create a ticket and I will be happy to help you out there. Thanks.

  15. November 12th, 2008 at 05:08 PM Gregory Says

    Hello,

    Thanks for the great plugin! I’ve got one question however, concerning searching: does search methods support UTF-8 characters or ASCII only?

    Thanks, regards.

  16. November 13th, 2008 at 03:32 AM Ben Johnson Says

    It supports whatever you have you system / database set up to support. It just sits on top of ActiveRecord and doesn’t really mess around with the character set. The only case where it could is in the keywords condition where it does some filtering. Even with that I account for foreign characters. Test it out, I am confident it will work properly with either character set, if it doesn’t let me know and we’ll get it working.

  17. November 13th, 2008 at 08:52 AM Gregory Says

    Hello Ben,

    Thanks for a fast reply. Actually I did some testing and my previous question is related to them. Searching in my web-app does not work properly if some outside-ASCII character is included in the searched phrase. At the beginning I thought it is something wrong with my db (or rails) settings but I’ve tested your “searchlogic example” available here: <http: /> and results were similar. If, say, I’d like to search ‘Zebra’ as the First Name Keyword, the app is returning 2 records which is OK. When I put ‘Żebra’ (with non-ascii character at the beginning) which is the Polish verb ‘to beg’ – it is not OK, because again 2 records are returned (the same records as in previous case). If I put the single letter ‘Ż’ as the First Name Keyword – all records are returned which suggests the app ignores non-ascii characters while searching.

    Anyway, irrespectively of what I wrote above, I think your plugin is really great.

    Thanks a lot, Gregory.

Leave a Reply