On 9/13/06, Tom Beddard <[EMAIL PROTECTED]> wrote:
> Using acts_as_ferret I'm trying to do a query like:
>
> active:(true) title|body:(#{params[:s]}) product_price:( >=
> #{params[:min]})
>
>
> Where I want to return only the active products that contain the search
> term in the title or body and has a minimum price >= params[:min]
>
> I'm finding that even though I'm indexing the product price as an
> integer (so no .00 to cause confusion) I'm getting results in the 50
> value range as well as 500 if I set the min price as 500. I presume
> ferret is doing the price as a string comparison, but is there any way
> to make it do a numeric match?
>
> Thanks

Hi Tom,

You need to pad all numbers to a fixed width when adding them to the
index as well as when querying the index. Usually you'd write the code
to do this yourself. I've recently come up with another way to do
this.

    require 'ferret'

    module Ferret::Analysis
      class IntegerTokenizer
        def initialize(num, width)
          @num = num.to_i
          @width = width
          @done = false
        end
        def next
          if @done
            return nil
          else
            @done = true
            puts Token.new("[EMAIL PROTECTED]" % @num, 0, @width)
            return Token.new("[EMAIL PROTECTED]" % @num, 0, @width)
          end
        end
        def text=(text)
          @num = text.to_i
          @done = false
        end
      end

      class IntegerAnalyzer
        def initialize(width)
          @width = width
        end
        def token_stream(field, input)
          return IntegerTokenizer.new(input, @width)
        end
      end
    end

    include Ferret::Analysis
    analyzer = PerFieldAnalyzer.new(StandardAnalyzer.new)
    analyzer[:num] = IntegerAnalyzer.new(5)

    index = Ferret::Index::Index.new(:analyzer => analyzer)
    docs = [
      {:num => 1,    :data => "yes"},
      {:num => 1,    :data => "no"},
      {:num => 10,   :data => "yes"},
      {:num => 10,   :data => "no"},
      {:num => 100,  :data => "yes"},
      {:num => 100,  :data => "no"},
      {:num => 1000, :data => "yes"},
      {:num => 1000, :data => "no"}
    ]

    docs.each { |d| index << d }

    puts index.process_query('data:yes AND num:[10 100]')
    puts index.search('data:yes AND num:[10 100]')

This will only work with the working copy of Ferret from the
subversion repository. I'm still not convinced that this is the best
way to do it.

Cheers,
Dave
_______________________________________________
Ferret-talk mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ferret-talk

Reply via email to