Ticket #339 (closed defect: fixed)

Opened 2 years ago

Last modified 2 years ago

RangeQuery bounds comparison does not handle negative numbers well

Reported by: philippe@… Owned by: somebody
Priority: major Milestone:
Component: component1 Version:
Keywords: Cc:

Description

I'm using RangeQuery? to query against positive and negative floats, and the comparison function to assert the bounds are ok uses strcmp, therefore it doesn't work well with negative numbers.

For positive numbers it works ok because the ascii codes of 1 is smaller than 2 in a string.

ferret/ruby/ext/r_search.c: line 1058

    if (*uterm && *lterm && (strcmp(*uterm, *lterm) < 0)) {
        rb_raise(rb_eArgError,
                 "The upper bound should greater than the lower bound."
                 " %s > %s", *lterm, *uterm);
    }

Maybe the code should test if the string is a number and just use a regular mathematics comparison.

Ideally the code would also handle floats!

Attachments

Change History

Changed 2 years ago by dbalmain

  • status changed from new to closed
  • resolution set to fixed

This is a little more difficult than it seems. There is also the problem of performance. When searching for ascii ranges the data is naturally ordered in the index so you scan skip right to the first term in the index and stop as soon as reach the last term. When doing integer or float comparisons you need to check all terms in the range from +.0 to 999999999999 (or there abouts). You also need to convert every one of those terms to a number to do the comparison.

So I decided to make a separate query to handle typed ranges call Ferret::Search::TypedRangeQuery?. This will work for integer, floats, hexadecimals and both positive and negative numbers. I've also made it the default range query for the Ferret::Index::Index class as it is probably closest to what the user expects. There will however still be cases where you'll want to stick with Ferret::Search::RangeQuery?, especially if you have a particularly large index.

Here is an example of TypedRangeQuery? usage;

tq = TypedRangeQuery.new(:temperature, :> -10.5, <= 4.6)
top_docs = index.search(tq)

# of course you could just use the query parser
top_docs = index.search('temperature:{-10.5, 4.6]')

Add/Change #339 (RangeQuery bounds comparison does not handle negative numbers well)

Author


E-mail address and user name can be saved in the Preferences.


Change Properties
<Author field>
Action
as closed
Next status will be 'reopened'
 
Note: See TracTickets for help on using tickets.