p.matsinopoulos
p.matsinopoulos

Reputation: 7810

While searching with sunspot_rails on Solr, how can I boost whole word matching over partial word matching?

I am using sunspot_rails to submit queries to a Solr instance. Everything works ok, but I want to order my results with the following criteria: I want to take first the documents where the matching term appears as word rather than as part of a word.

Hence, if I have the two documents:

1) Solr searching with Solr is fantastic

and

2) Solr is very good to support search with free text

and the term I am looking for is : search, then

I want to take both documents in the results, but I want document (2) to appear first.

I have tried order_by :score, :desc but it does not seem to be working. Unless I find a way to tell how the "score" is calculated.

Thanks in advance Panayotis

Upvotes: 4

Views: 880

Answers (2)

Nick Zadrozny
Nick Zadrozny

Reputation: 7944

Expanding on Jayendra's answer a bit, you should index into two separate fields.

Here's an example schema.xml excerpt for Sunspot, from my answer to an earlier question: How to boost longer ngrams in solr?

<schema>
  <types>

    <!--
      A text type with minimal text processing, for the greatest semantic
      value in a term match. Boost this field heavily.
    -->
    <fieldType name="text" class="solr.TextField" omitNorms="false">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory" />
        <filter class="solr.StandardFilterFactory" />
        <filter class="solr.LowerCaseFilterFactory" />
      </analyzer>
    </fieldType>

    <!--
      Looser matches with NGram processing for substrings of terms and synonyms
    -->
    <fieldType name="text_ngram" class="solr.TextField" omitNorms="false">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory" />
        <filter class="solr.StandardFilterFactory" />
        <filter class="solr.LowerCaseFilterFactory" />
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" />
        <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="6" side="front" />
      </analyzer>
    </fieldType>

    <!-- other stuff -->

  </types>
  <fields>

    <!-- other fields; refer to *_text -->

    <dynamicField name="*_ngram" type="text_ngram" ... />

  </fields>
</schema>

In your searchable block, you can use the :as option to specify the fieldname:

searchable do 

  text :title
  text :title, :as => :title_ngram

  # ...

end

Upvotes: 1

Jayendra
Jayendra

Reputation: 52769

You would need to maintain two fields with Solr.
One with the Original value and other with the analyzed value.e.g. text_org and text (which is analyzed)
Then you can adjust the boost accordingly, boosting the original field value over the analyzed one e.g. text_org^2 text^1
Remember if it matches the original, it will also match the analyzed text or the effect for the exact whole word match is more then the normal match.

Upvotes: 3

Related Questions