Ch4rAss
Ch4rAss

Reputation: 754

Thinking Sphinx without condition

I have a following model:

class Article < ActiveRecord::Base

  define_index do
    indexes content
    indexes :name, sortable: true
    has type
  end
end

and special type of an article is:

class About < Article
end

and the same for Contact

I would like to have searchable articles index action without articles with type of "About" or "Contact"

class ArticlesController < ApplicationController
  load_and_authorize_resource

  def index
    @articles = Article.search(params[:search],
                               :with_all => {:type => nil},
                               :page => params[:page],
                               :per_page => 10)
  end
end

But the @articles instance variable contains everytime also "About" & "Contact" articles.

This is very strange (seems like will_paginate messing everything up):

@articles = Article.search(
  :without =>  {:type => %w(About Contact)}).include?(About.first) # false

@articles = Article.search(
  :without =>  {:type => %w(About Contact)},
  :page => 1,
  :per_page => 1000).include?(About.first) # true

=============================================================================

Finally I did:

class Article < ActiveRecord::Base

  define_index do
    indexes content
    indexes :name, sortable: true

    has "CRC32(type)", :as => :article_type, :type => :integer
  end
end

and:

class ArticlesController < ApplicationController

  load_and_authorize_resource

  def index
     @articles = Article.search(params[:search],
                               :without =>  {:article_type => ["About".to_crc32, "Contact".to_crc32]},
                               :page => params[:page],
                               :per_page => 10)
  end
end

and it works. Thanks guys!

Upvotes: 0

Views: 1099

Answers (3)

fuzzyalej
fuzzyalej

Reputation: 5973

From the Thinking Sphinx FAQ:

Filtering on String Attributes

While you can have string columns as attributes in Sphinx, they aren’t stored as strings. Instead, Sphinx figures out the alphabetical order, and gives each string an integer value to make them useful for sorting. However, this means it’s close to impossible to filter on these attributes.

So, to get around this, there’s two options: firstly, use integer attributes instead, if you possibly can. This works for small result sets (for example: gender). Otherwise, you might want to consider manually converting the string to a CRC integer value:

has "CRC32(category)", :as => :category, :type => :integer

This way, you can filter on it like so:

Article.search 'pancakes', :with => { :category => 'Ruby'.to_crc32 }

Of course, this isn’t amazingly clean, but it will work quite well. You should also take note that CRC32 encoding can have collisions, so it’s not the perfect solution.

Upvotes: 2

Sandip Ransing
Sandip Ransing

Reputation: 7733

Exclude About & Contact type from conditions like -

@articles = Article.search(params[:search],
             :without => {:type => %w(About Contact)},
             :page => params[:page],
             :per_page => 10)

OR

I am not very sure on below but you can give it try..

  define_index do
    indexes content
    indexes :name, sortable: true
    indexes(:type), :as => :article_type
  end

    @articles = Article.search(params[:search],
                 :without => {:article_type => %w(About Contact)},
                 :page => params[:page],
                 :per_page => 10)

Also, make sure inside your database records you have type attribute got inserted properly..

Upvotes: 1

Jimmy Baker
Jimmy Baker

Reputation: 3255

Couldn't you use "with" instead of "with_all"? For example:

@articles = Article.search(params[:search],
                               :with => {:type => nil},
                               :page => params[:page],
                               :per_page => 10)

Upvotes: 0

Related Questions