Forum: Ferret Boost Sorting with Acts_as_ferret?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2d3a6cee81a4dd2b7ea1902a435bb421?d=identicon&s=25 Gregg Pollack (patched)
on 2007-02-03 01:00
Hey guys,

    Simple question here.

    I have a single index of recipes, from which I'm looking at the
following fields:  Name, Ingredient Text, Tags, and Description.

    The key is, I want to show all the results that come from Name,
before I show any of the results from Ingredient Text, Tags, or
Description.

    I tried doing this:

acts_as_ferret :fields => {
   :name => {:boost => 9000, :store => :yes},
   :ingredients => {:boost => 6000, :store => :yes},
   :tags => {:boost => 3000, :store => :yes},
   :description => {:boost => 1, :store => :yes}}

    I figured if I put huge boost on my fields, the "name" results would
always come before ingredients (no matter what the score).

    Can anyone throw me any ideas on how one might do this?  Here is an
explain of one of my first results.  Perhaps I need to change the
rounding of my score?  I dunno.

Basque chicken scored 1.0
3291.866 = product of:
  6583.732 = sum of:
    674.6201 = weight(ingredients_without_brackets:chicken in 12670),
product of:
      0.2805449 = query_weight(ingredients_without_brackets:chicken),
product of:
        3.13109 = idf(doc_freq=2145)
        0.08959977 = query_norm
      2404.677 = field_weight(ingredients_without_brackets:chicken in
12670), product of:
        1.0 = tf(term_freq(ingredients_without_brackets:chicken)=1)
        3.13109 = idf(doc_freq=2145)
        768.0 = field_norm(field=ingredients_without_brackets,
doc=12670)
    5909.112 = weight(tags_with_spaces:chicken in 12670), product of:
      0.4547729 = query_weight(tags_with_spaces:chicken), product of:
        5.075603 = idf(doc_freq=306)
        0.08959977 = query_norm
      12993.54 = field_weight(tags_with_spaces:chicken in 12670),
product of:
        1.0 = tf(term_freq(tags_with_spaces:chicken)=1)
        5.075603 = idf(doc_freq=306)
        2560.0 = field_norm(field=tags_with_spaces, doc=12670)
  0.5 = coord(2/4)

   Thanks in advance,

-Gregg
C9dd93aa135988cabf9183d3210665ca?d=identicon&s=25 Jens Kraemer (Guest)
on 2007-02-04 18:26
(Received via mailing list)
Hi!

On Sat, Feb 03, 2007 at 01:00:49AM +0100, Gregg Pollack wrote:
>
>     I tried doing this:
>
> acts_as_ferret :fields => {
>    :name => {:boost => 9000, :store => :yes},
>    :ingredients => {:boost => 6000, :store => :yes},
>    :tags => {:boost => 3000, :store => :yes},
>    :description => {:boost => 1, :store => :yes}}
>
>     I figured if I put huge boost on my fields, the "name" results would
> always come before ingredients (no matter what the score).

souunds reasonable.

>     Can anyone throw me any ideas on how one might do this?  Here is an
> explain of one of my first results.  Perhaps I need to change the
> rounding of my score?  I dunno.

Scores are always between 0 and 1. You might want to set some less
aggressive values for your boost values, it's more the relation between
them that counts, than their absolute value.

However that way you won't have a guarantee that the sorting will be
as you intend. If this really is that important, run an explicit
search only against the name field, and then one against all fields,
excluding the hits you got with the first search:

# get results where name fields match (might be good to escape at least
# '(' and ')' in query):
name_results = Recipe.find_by_contents(%{name:(#{query})})

# now get results where other fields match, but exclude those we already
# have:
ids = name_results.map(&:id).join ' OR '
other_results = Recipe.find_by_contents(%{#{query} -id:(#{ids})"})




Jens



--
webit! Gesellschaft für neue Medien mbH          www.webit.de
Dipl.-Wirtschaftsingenieur Jens Krämer       kraemer@webit.de
Schnorrstraße 76                         Tel +49 351 46766  0
D-01069 Dresden                          Fax +49 351 46766 66
2d3a6cee81a4dd2b7ea1902a435bb421?d=identicon&s=25 Gregg Pollack (patched)
on 2007-02-04 20:10
Jens,

    Thanks for the suggestion.  However, in this case the #ids field
could contain a thousand ids, which I'm not sure is good.

    However, you just gave me another idea that involves 4 queries, but
it doesn't seem to be working as it should.  Can you see why?

q = "chicken"

# lets get the total (where it's found in all the fields)
total = index.search_each(q) do |doc, score| end
puts "Total should be = #{total}"

# find count of just name results
query = qp.parse("+name:(#{q})")
puts query.to_s
total = index.search_each(query) do |doc, score| end
puts "total with name = #{total}"

# find all results where query is in ingredients but excluding the name
results
query = qp.parse("+ingredients:(#{q}) -name:(#{q})")
puts query.to_s
total = index.search_each(query) do |doc, score| end
puts "total with ingredients = #{total}"

query = qp.parse("+tags:(#{q}) -name:(#{q}) -ingredients:(#{q})")
puts query.to_s
total = index.search_each(query) do |doc, score| end
puts "total with tags = #{total}"

query = qp.parse("+description:(#{q}) -name:(#{q}) -ingredients:(#{q})
-tags:(#{q})")
puts query.to_s
total = index.search_each(query) do |doc, score| end
puts "total with desc = #{total}"

    You would think that these fields would add up, but here are the
results:

Total should be = 2225

name:chicken
total with name = 1028

+ingredients:chicken -name:chicken
total with ingredients = 2115

+tags:chicken -name:chicken -ingredients:chicken
total with tags = 18

+description:chicken -name:chicken -ingredients:chicken -tags:chicken
total with desc = 1

  As you can see, the numbers aren't adding up, but shouldn't they be?

  Thanks in advance for your help.
This topic is locked and can not be replied to.