How do I make the QueryParser in Lucene handle numeric ranges?

前端 未结 5 1124
闹比i
闹比i 2020-12-16 05:43
new QueryParser(.... ).parse (somequery);

it works only for string indexed fields. Say i have a field called count where count is a integer field (

5条回答
  •  生来不讨喜
    2020-12-16 06:24

    I adapted Jeremies answer for C# and Lucene.Net 3.0.3. I also needed type double instead of int. This is my code:

    using System.Globalization;
    using Lucene.Net.Analysis;
    using Lucene.Net.Index;
    using Lucene.Net.QueryParsers;
    using Lucene.Net.Search;
    using Lucene.Net.Util;
    using Version = Lucene.Net.Util.Version;
    
    namespace SearchServer.SearchEngine
    {
        internal class SearchQueryParser : QueryParser
        {
            public SearchQueryParser(Analyzer analyzer)
                : base(Version.LUCENE_30, null, analyzer)
            {
            }
    
            private const NumberStyles DblNumberStyles = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint;
    
            protected override Query NewRangeQuery(string field, string part1, string part2, bool inclusive)
            {
                if (field == "p")
                {
                    double part1Dbl;
                    if (!double.TryParse(part1, DblNumberStyles, CultureInfo.InvariantCulture, out part1Dbl))
                        throw new ParseException($"Error parsing value {part1} for field {field} as double.");
                    double part2Dbl;
                    if (!double.TryParse(part2, DblNumberStyles, CultureInfo.InvariantCulture, out part2Dbl))
                        throw new ParseException($"Error parsing value {part2} for field {field} as double.");
                    return NumericRangeQuery.NewDoubleRange(field, part1Dbl, part2Dbl, inclusive, inclusive);
                }
                return base.NewRangeQuery(field, part1, part2, inclusive);
            }
    
            protected override Query NewTermQuery(Term term)
            {
                if (term.Field == "p")
                {
                    double dblParsed;
                    if (!double.TryParse(term.Text, DblNumberStyles, CultureInfo.InvariantCulture, out dblParsed))
                        throw new ParseException($"Error parsing value {term.Text} for field {term.Field} as double.");
                    return new TermQuery(new Term(term.Field, NumericUtils.DoubleToPrefixCoded(dblParsed)));
                }
                return base.NewTermQuery(term);
            }
        }
    }
    

    I improved my code to also allow queries like greater than and lower than when an asterisk is passed. E.g. p:[* TO 5]

    ...
        double? part1Dbl = null;
        double tmpDbl;
        if (part1 != "*")
        {
            if (!double.TryParse(part1, DblNumberStyles, CultureInfo.InvariantCulture, out tmpDbl))
                throw new ParseException($"Error parsing value {part1} for field {field} as double.");
            part1Dbl = tmpDbl;
        }
        double? part2Dbl = null;
        if (part2 != "*")
        {
            if (!double.TryParse(part2, DblNumberStyles, CultureInfo.InvariantCulture, out tmpDbl))
                throw new ParseException($"Error parsing value {part2} for field {field} as double.");
            part2Dbl = tmpDbl;
        }
        return NumericRangeQuery.NewDoubleRange(field, part1Dbl, part2Dbl, inclusive, inclusive);
    ...
    

提交回复
热议问题