Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
NumericRangeQuery.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 using Lucene.Net.Index;
21 using NumericTokenStream = Lucene.Net.Analysis.NumericTokenStream;
22 using NumericField = Lucene.Net.Documents.NumericField;
23 using IndexReader = Lucene.Net.Index.IndexReader;
24 using Term = Lucene.Net.Index.Term;
25 using NumericUtils = Lucene.Net.Util.NumericUtils;
26 using StringHelper = Lucene.Net.Util.StringHelper;
27 using ToStringUtils = Lucene.Net.Util.ToStringUtils;
28 
29 namespace Lucene.Net.Search
30 {
31 
32  /// <summary> <p/>A <see cref="Query" /> that matches numeric values within a
33  /// specified range. To use this, you must first index the
34  /// numeric values using <see cref="NumericField" /> (expert: <see cref="NumericTokenStream" />
35  ///). If your terms are instead textual,
36  /// you should use <see cref="TermRangeQuery" />. <see cref="NumericRangeFilter{T}" />
37  /// is the filter equivalent of this
38  /// query.<p/>
39  ///
40  /// <p/>You create a new NumericRangeQuery with the static
41  /// factory methods, eg:
42  ///
43  /// <code>
44  /// Query q = NumericRangeQuery.newFloatRange("weight",
45  /// new Float(0.3f), new Float(0.10f),
46  /// true, true);
47  /// </code>
48  ///
49  /// matches all documents whose float valued "weight" field
50  /// ranges from 0.3 to 0.10, inclusive.
51  ///
52  /// <p/>The performance of NumericRangeQuery is much better
53  /// than the corresponding <see cref="TermRangeQuery" /> because the
54  /// number of terms that must be searched is usually far
55  /// fewer, thanks to trie indexing, described below.<p/>
56  ///
57  /// <p/>You can optionally specify a <a
58  /// href="#precisionStepDesc"><c>precisionStep</c></a>
59  /// when creating this query. This is necessary if you've
60  /// changed this configuration from its default (4) during
61  /// indexing. Lower values consume more disk space but speed
62  /// up searching. Suitable values are between <b>1</b> and
63  /// <b>8</b>. A good starting point to test is <b>4</b>,
64  /// which is the default value for all <c>Numeric*</c>
65  /// classes. See <a href="#precisionStepDesc">below</a> for
66  /// details.
67  ///
68  /// <p/>This query defaults to
69  /// <see cref="MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT"/> for
70  /// 32 bit (int/float) ranges with precisionStep &lt;8 and 64
71  /// bit (long/double) ranges with precisionStep &lt;6.
72  /// Otherwise it uses
73  /// <see cref="MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE"/> as the
74  /// number of terms is likely to be high. With precision
75  /// steps of &lt;4, this query can be run with one of the
76  /// BooleanQuery rewrite methods without changing
77  /// BooleanQuery's default max clause count.
78  ///
79  /// <p/><font color="red"><b>NOTE:</b> This API is experimental and
80  /// might change in incompatible ways in the next release.</font>
81  ///
82  /// <br/><h3>How it works</h3>
83  ///
84  /// <p/>See the publication about <a target="_blank" href="http://www.panfmp.org">panFMP</a>,
85  /// where this algorithm was described (referred to as <c>TrieRangeQuery</c>):
86  ///
87  /// <blockquote><strong>Schindler, U, Diepenbroek, M</strong>, 2008.
88  /// <em>Generic XML-based Framework for Metadata Portals.</em>
89  /// Computers &amp; Geosciences 34 (12), 1947-1955.
90  /// <a href="http://dx.doi.org/10.1016/j.cageo.2008.02.023"
91  /// target="_blank">doi:10.1016/j.cageo.2008.02.023</a></blockquote>
92  ///
93  /// <p/><em>A quote from this paper:</em> Because Apache Lucene is a full-text
94  /// search engine and not a conventional database, it cannot handle numerical ranges
95  /// (e.g., field value is inside user defined bounds, even dates are numerical values).
96  /// We have developed an extension to Apache Lucene that stores
97  /// the numerical values in a special string-encoded format with variable precision
98  /// (all numerical values like doubles, longs, floats, and ints are converted to
99  /// lexicographic sortable string representations and stored with different precisions
100  /// (for a more detailed description of how the values are stored,
101  /// see <see cref="NumericUtils" />). A range is then divided recursively into multiple intervals for searching:
102  /// The center of the range is searched only with the lowest possible precision in the <em>trie</em>,
103  /// while the boundaries are matched more exactly. This reduces the number of terms dramatically.<p/>
104  ///
105  /// <p/>For the variant that stores long values in 8 different precisions (each reduced by 8 bits) that
106  /// uses a lowest precision of 1 byte, the index contains only a maximum of 256 distinct values in the
107  /// lowest precision. Overall, a range could consist of a theoretical maximum of
108  /// <c>7*255*2 + 255 = 3825</c> distinct terms (when there is a term for every distinct value of an
109  /// 8-byte-number in the index and the range covers almost all of them; a maximum of 255 distinct values is used
110  /// because it would always be possible to reduce the full 256 values to one term with degraded precision).
111  /// In practice, we have seen up to 300 terms in most cases (index with 500,000 metadata records
112  /// and a uniform value distribution).<p/>
113  ///
114  /// <a name="precisionStepDesc"/><h3>Precision Step</h3>
115  /// <p/>You can choose any <c>precisionStep</c> when encoding values.
116  /// Lower step values mean more precisions and so more terms in index (and index gets larger).
117  /// On the other hand, the maximum number of terms to match reduces, which optimized query speed.
118  /// The formula to calculate the maximum term count is:
119  /// <code>
120  /// n = [ (bitsPerValue/precisionStep - 1) * (2^precisionStep - 1 ) * 2 ] + (2^precisionStep - 1 )
121  /// </code>
122  /// <p/><em>(this formula is only correct, when <c>bitsPerValue/precisionStep</c> is an integer;
123  /// in other cases, the value must be rounded up and the last summand must contain the modulo of the division as
124  /// precision step)</em>.
125  /// For longs stored using a precision step of 4, <c>n = 15*15*2 + 15 = 465</c>, and for a precision
126  /// step of 2, <c>n = 31*3*2 + 3 = 189</c>. But the faster search speed is reduced by more seeking
127  /// in the term enum of the index. Because of this, the ideal <c>precisionStep</c> value can only
128  /// be found out by testing. <b>Important:</b> You can index with a lower precision step value and test search speed
129  /// using a multiple of the original step value.<p/>
130  ///
131  /// <p/>Good values for <c>precisionStep</c> are depending on usage and data type:
132  /// <list type="bullet">
133  /// <item>The default for all data types is <b>4</b>, which is used, when no <c>precisionStep</c> is given.</item>
134  /// <item>Ideal value in most cases for <em>64 bit</em> data types <em>(long, double)</em> is <b>6</b> or <b>8</b>.</item>
135  /// <item>Ideal value in most cases for <em>32 bit</em> data types <em>(int, float)</em> is <b>4</b>.</item>
136  /// <item>Steps <b>&gt;64</b> for <em>long/double</em> and <b>&gt;32</b> for <em>int/float</em> produces one token
137  /// per value in the index and querying is as slow as a conventional <see cref="TermRangeQuery" />. But it can be used
138  /// to produce fields, that are solely used for sorting (in this case simply use <see cref="int.MaxValue" /> as
139  /// <c>precisionStep</c>). Using <see cref="NumericField">NumericFields</see> for sorting
140  /// is ideal, because building the field cache is much faster than with text-only numbers.
141  /// Sorting is also possible with range query optimized fields using one of the above <c>precisionSteps</c>.</item>
142  /// </list>
143  ///
144  /// <p/>Comparisons of the different types of RangeQueries on an index with about 500,000 docs showed
145  /// that <see cref="TermRangeQuery" /> in boolean rewrite mode (with raised <see cref="BooleanQuery" /> clause count)
146  /// took about 30-40 secs to complete, <see cref="TermRangeQuery" /> in constant score filter rewrite mode took 5 secs
147  /// and executing this class took &lt;100ms to complete (on an Opteron64 machine, Java 1.5, 8 bit
148  /// precision step). This query type was developed for a geographic portal, where the performance for
149  /// e.g. bounding boxes or exact date/time stamps is important.<p/>
150  ///
151  /// </summary>
152  /// <since> 2.9
153  ///
154  /// </since>
155  [Serializable]
156  public sealed class NumericRangeQuery<T> : MultiTermQuery
157  where T : struct, IComparable<T> // best equiv constraint for java's number class
158  {
159  internal NumericRangeQuery(System.String field, int precisionStep, int valSize, T? min, T? max, bool minInclusive, bool maxInclusive)
160  {
161  System.Diagnostics.Debug.Assert((valSize == 32 || valSize == 64));
162  if (precisionStep < 1)
163  throw new System.ArgumentException("precisionStep must be >=1");
164  this.field = StringHelper.Intern(field);
165  this.precisionStep = precisionStep;
166  this.valSize = valSize;
167  this.min = min;
168  this.max = max;
169  this.minInclusive = minInclusive;
170  this.maxInclusive = maxInclusive;
171 
172  // For bigger precisionSteps this query likely
173  // hits too many terms, so set to CONSTANT_SCORE_FILTER right off
174  // (especially as the FilteredTermEnum is costly if wasted only for AUTO tests because it
175  // creates new enums from IndexReader for each sub-range)
176  switch (valSize)
177  {
178 
179  case 64:
180  RewriteMethod = (precisionStep > 6)?CONSTANT_SCORE_FILTER_REWRITE:CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
181  break;
182 
183  case 32:
184  RewriteMethod = (precisionStep > 8)?CONSTANT_SCORE_FILTER_REWRITE:CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
185  break;
186 
187  default:
188  // should never happen
189  throw new System.ArgumentException("valSize must be 32 or 64");
190 
191  }
192 
193  // shortcut if upper bound == lower bound
194  if (min != null && min.Equals(max))
195  {
196  RewriteMethod = CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE;
197  }
198  }
199 
200  //@Override
201  protected internal override FilteredTermEnum GetEnum(IndexReader reader)
202  {
203  return new NumericRangeTermEnum(this, reader);
204  }
205 
206  /// <summary>Returns the field name for this query </summary>
207  public string Field
208  {
209  get { return field; }
210  }
211 
212  /// <summary>Returns <c>true</c> if the lower endpoint is inclusive </summary>
213  public bool IncludesMin
214  {
215  get { return minInclusive; }
216  }
217 
218  /// <summary>Returns <c>true</c> if the upper endpoint is inclusive </summary>
219  public bool IncludesMax
220  {
221  get { return maxInclusive; }
222  }
223 
224  /// <summary>Returns the lower value of this range query </summary>
225  public T? Min
226  {
227  get { return min; }
228  }
229 
230  /// <summary>Returns the upper value of this range query </summary>
231  public T? Max
232  {
233  get { return max; }
234  }
235 
236  public override System.String ToString(System.String field)
237  {
238  System.Text.StringBuilder sb = new System.Text.StringBuilder();
239  if (!this.field.Equals(field))
240  sb.Append(this.field).Append(':');
241  return sb.Append(minInclusive ? '[' : '{').Append((min == null) ? "*" : min.ToString()).Append(" TO ").Append((max == null) ? "*" : max.ToString()).Append(maxInclusive ? ']' : '}').Append(ToStringUtils.Boost(Boost)).ToString();
242  }
243 
244  public override bool Equals(System.Object o)
245  {
246  if (o == this)
247  return true;
248  if (!base.Equals(o))
249  return false;
250  if (o is NumericRangeQuery<T>)
251  {
252  NumericRangeQuery<T> q = (NumericRangeQuery<T>)o;
253  return ((System.Object)field == (System.Object)q.field && (q.min == null ? min == null : q.min.Equals(min)) && (q.max == null ? max == null : q.max.Equals(max)) && minInclusive == q.minInclusive && maxInclusive == q.maxInclusive && precisionStep == q.precisionStep);
254  }
255  return false;
256  }
257 
258  public override int GetHashCode()
259  {
260  int hash = base.GetHashCode();
261  hash += (field.GetHashCode() ^ 0x4565fd66 + precisionStep ^ 0x64365465);
262  if (min != null)
263  hash += (min.GetHashCode() ^ 0x14fa55fb);
264  if (max != null)
265  hash += (max.GetHashCode() ^ 0x733fa5fe);
266  return hash + (minInclusive.GetHashCode() ^ 0x14fa55fb) + (maxInclusive.GetHashCode() ^ 0x733fa5fe);
267  }
268 
269  // field must be interned after reading from stream
270  //private void ReadObject(java.io.ObjectInputStream in)
271  //{
272  // in.defaultReadObject();
273  // field = StringHelper.intern(field);
274  //}
275 
276 
277  [System.Runtime.Serialization.OnDeserialized]
278  internal void OnDeserialized(System.Runtime.Serialization.StreamingContext context)
279  {
280  field = StringHelper.Intern(field);
281  }
282 
283  // members (package private, to be also fast accessible by NumericRangeTermEnum)
284  internal System.String field;
285  internal int precisionStep;
286  internal int valSize;
287  internal T? min;
288  internal T? max;
289  internal bool minInclusive;
290  internal bool maxInclusive;
291 
292  /// <summary> Subclass of FilteredTermEnum for enumerating all terms that match the
293  /// sub-ranges for trie range queries.
294  /// <p/>
295  /// WARNING: This term enumeration is not guaranteed to be always ordered by
296  /// <see cref="Term.CompareTo(Term)" />.
297  /// The ordering depends on how <see cref="NumericUtils.SplitLongRange" /> and
298  /// <see cref="NumericUtils.SplitIntRange" /> generates the sub-ranges. For
299  /// <see cref="MultiTermQuery" /> ordering is not relevant.
300  /// </summary>
301  private sealed class NumericRangeTermEnum:FilteredTermEnum
302  {
303  private class AnonymousClassLongRangeBuilder:NumericUtils.LongRangeBuilder
304  {
305  public AnonymousClassLongRangeBuilder(NumericRangeTermEnum enclosingInstance)
306  {
307  InitBlock(enclosingInstance);
308  }
309  private void InitBlock(NumericRangeTermEnum enclosingInstance)
310  {
311  this.enclosingInstance = enclosingInstance;
312  }
313  private NumericRangeTermEnum enclosingInstance;
314  public NumericRangeTermEnum Enclosing_Instance
315  {
316  get
317  {
318  return enclosingInstance;
319  }
320 
321  }
322  //@Override
323  public override void AddRange(System.String minPrefixCoded, System.String maxPrefixCoded)
324  {
325  Enclosing_Instance.rangeBounds.AddLast(minPrefixCoded);
326  Enclosing_Instance.rangeBounds.AddLast(maxPrefixCoded);
327  }
328  }
329  private class AnonymousClassIntRangeBuilder:NumericUtils.IntRangeBuilder
330  {
331  public AnonymousClassIntRangeBuilder(NumericRangeTermEnum enclosingInstance)
332  {
333  InitBlock(enclosingInstance);
334  }
335  private void InitBlock(NumericRangeTermEnum enclosingInstance)
336  {
337  this.enclosingInstance = enclosingInstance;
338  }
339  private NumericRangeTermEnum enclosingInstance;
340  public NumericRangeTermEnum Enclosing_Instance
341  {
342  get
343  {
344  return enclosingInstance;
345  }
346 
347  }
348  //@Override
349  public override void AddRange(System.String minPrefixCoded, System.String maxPrefixCoded)
350  {
351  Enclosing_Instance.rangeBounds.AddLast(minPrefixCoded);
352  Enclosing_Instance.rangeBounds.AddLast(maxPrefixCoded);
353  }
354  }
355  private void InitBlock(NumericRangeQuery<T> enclosingInstance)
356  {
357  this.enclosingInstance = enclosingInstance;
358  termTemplate = new Term(Enclosing_Instance.field);
359  }
360  private NumericRangeQuery<T> enclosingInstance;
361  public NumericRangeQuery<T> Enclosing_Instance
362  {
363  get
364  {
365  return enclosingInstance;
366  }
367 
368  }
369 
370  private IndexReader reader;
371  private LinkedList<string> rangeBounds = new LinkedList<string>();
372  private Term termTemplate;
373  private System.String currentUpperBound = null;
374 
375  private bool isDisposed;
376 
377  internal NumericRangeTermEnum(NumericRangeQuery<T> enclosingInstance, IndexReader reader)
378  {
379  InitBlock(enclosingInstance);
380  this.reader = reader;
381 
382  Type rangeType = Nullable.GetUnderlyingType(typeof(T?));
383  switch (Enclosing_Instance.valSize)
384  {
385  case 64: {
386  // lower
387  long minBound = System.Int64.MinValue;
388  if (rangeType == typeof(System.Int64))
389  {
390  // added in these checks to emulate java. passing null give it no type (in old code),
391  // but .net can identifies it with generics and sets the bounds to 0, causing tests to fail
392  if (Enclosing_Instance.min != null)
393  minBound = System.Convert.ToInt64(Enclosing_Instance.min);
394  }
395  else if (rangeType == typeof(System.Double))
396  {
397  if (Enclosing_Instance.min != null)
398  minBound = NumericUtils.DoubleToSortableLong(System.Convert.ToDouble(Enclosing_Instance.min));
399  }
400  if (!Enclosing_Instance.minInclusive && Enclosing_Instance.min != null)
401  {
402  if (minBound == System.Int64.MaxValue)
403  break;
404  minBound++;
405  }
406 
407  // upper
408  long maxBound = System.Int64.MaxValue;
409  if (rangeType == typeof(System.Int64))
410  {
411  if (Enclosing_Instance.max != null)
412  maxBound = System.Convert.ToInt64(Enclosing_Instance.max);
413  }
414  else if (rangeType == typeof(System.Double))
415  {
416  if (Enclosing_Instance.max != null)
417  maxBound = NumericUtils.DoubleToSortableLong(System.Convert.ToDouble(Enclosing_Instance.max));
418  }
419  if (!Enclosing_Instance.maxInclusive && Enclosing_Instance.max != null)
420  {
421  if (maxBound == System.Int64.MinValue)
422  break;
423  maxBound--;
424  }
425 
426  NumericUtils.SplitLongRange(new AnonymousClassLongRangeBuilder(this), Enclosing_Instance.precisionStep, minBound, maxBound);
427  break;
428  }
429 
430 
431  case 32: {
432  // lower
433  int minBound = System.Int32.MinValue;
434  if (rangeType == typeof(System.Int32))
435  {
436  if (Enclosing_Instance.min != null)
437  minBound = System.Convert.ToInt32(Enclosing_Instance.min);
438  }
439  else if (rangeType == typeof(System.Single))
440  {
441  if (Enclosing_Instance.min != null)
442  minBound = NumericUtils.FloatToSortableInt(System.Convert.ToSingle(Enclosing_Instance.min));
443  }
444  if (!Enclosing_Instance.minInclusive && Enclosing_Instance.min != null)
445  {
446  if (minBound == System.Int32.MaxValue)
447  break;
448  minBound++;
449  }
450 
451  // upper
452  int maxBound = System.Int32.MaxValue;
453  if (rangeType == typeof(System.Int32))
454  {
455  if (Enclosing_Instance.max != null)
456  maxBound = System.Convert.ToInt32(Enclosing_Instance.max);
457  }
458  else if (rangeType == typeof(System.Single))
459  {
460  if (Enclosing_Instance.max != null)
461  maxBound = NumericUtils.FloatToSortableInt(System.Convert.ToSingle(Enclosing_Instance.max));
462  }
463  if (!Enclosing_Instance.maxInclusive && Enclosing_Instance.max != null)
464  {
465  if (maxBound == System.Int32.MinValue)
466  break;
467  maxBound--;
468  }
469 
470  NumericUtils.SplitIntRange(new AnonymousClassIntRangeBuilder(this), Enclosing_Instance.precisionStep, minBound, maxBound);
471  break;
472  }
473 
474 
475  default:
476  // should never happen
477  throw new System.ArgumentException("valSize must be 32 or 64");
478 
479  }
480 
481  // seek to first term
482  Next();
483  }
484 
485  //@Override
486  public override float Difference()
487  {
488  return 1.0f;
489  }
490 
491  /// <summary>this is a dummy, it is not used by this class. </summary>
492  //@Override
493  public override bool EndEnum()
494  {
495  throw new NotSupportedException("not implemented");
496  }
497 
498  /// <summary>this is a dummy, it is not used by this class. </summary>
499  protected internal override void SetEnum(TermEnum tenum)
500  {
501  throw new NotSupportedException("not implemented");
502  }
503 
504  /// <summary> Compares if current upper bound is reached,
505  /// this also updates the term count for statistics.
506  /// In contrast to <see cref="FilteredTermEnum" />, a return value
507  /// of <c>false</c> ends iterating the current enum
508  /// and forwards to the next sub-range.
509  /// </summary>
510  //@Override
511  protected internal override bool TermCompare(Term term)
512  {
513  return (term.Field == Enclosing_Instance.field && String.CompareOrdinal(term.Text, currentUpperBound) <= 0);
514  }
515 
516  /// <summary>Increments the enumeration to the next element. True if one exists. </summary>
517  //@Override
518  public override bool Next()
519  {
520  // if a current term exists, the actual enum is initialized:
521  // try change to next term, if no such term exists, fall-through
522  if (currentTerm != null)
523  {
524  System.Diagnostics.Debug.Assert(actualEnum != null);
525  if (actualEnum.Next())
526  {
527  currentTerm = actualEnum.Term;
528  if (TermCompare(currentTerm))
529  return true;
530  }
531  }
532  // if all above fails, we go forward to the next enum,
533  // if one is available
534  currentTerm = null;
535  while (rangeBounds.Count >= 2)
536  {
537  // close the current enum and read next bounds
538  if (actualEnum != null)
539  {
540  actualEnum.Close();
541  actualEnum = null;
542  }
543  string lowerBound = rangeBounds.First.Value;
544  rangeBounds.RemoveFirst();
545  this.currentUpperBound = rangeBounds.First.Value;
546  rangeBounds.RemoveFirst();
547  // create a new enum
548  actualEnum = reader.Terms(termTemplate.CreateTerm(lowerBound));
549  currentTerm = actualEnum.Term;
550  if (currentTerm != null && TermCompare(currentTerm))
551  return true;
552  // clear the current term for next iteration
553  currentTerm = null;
554  }
555 
556  // no more sub-range enums available
557  System.Diagnostics.Debug.Assert(rangeBounds.Count == 0 && currentTerm == null);
558  return false;
559  }
560 
561  /// <summary>Closes the enumeration to further activity, freeing resources. </summary>
562  protected override void Dispose(bool disposing)
563  {
564  if (isDisposed) return;
565 
566  rangeBounds.Clear();
567  currentUpperBound = null;
568 
569  isDisposed = true;
570  base.Dispose(disposing);
571  }
572  }
573  }
574 
575  public static class NumericRangeQuery
576  {
577  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>long</c>
578  /// range using the given <a href="#precisionStepDesc"><c>precisionStep</c></a>.
579  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
580  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
581  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
582  /// </summary>
583  public static NumericRangeQuery<long> NewLongRange(System.String field, int precisionStep, long? min, long? max, bool minInclusive, bool maxInclusive)
584  {
585  return new NumericRangeQuery<long>(field, precisionStep, 64, min, max, minInclusive, maxInclusive);
586  }
587 
588  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>long</c>
589  /// range using the default <c>precisionStep</c> <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4).
590  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
591  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
592  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
593  /// </summary>
594  public static NumericRangeQuery<long> NewLongRange(System.String field, long? min, long? max, bool minInclusive, bool maxInclusive)
595  {
596  return new NumericRangeQuery<long>(field, NumericUtils.PRECISION_STEP_DEFAULT, 64, min, max, minInclusive, maxInclusive);
597  }
598 
599  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>int</c>
600  /// range using the given <a href="#precisionStepDesc"><c>precisionStep</c></a>.
601  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
602  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
603  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
604  /// </summary>
605  public static NumericRangeQuery<int> NewIntRange(System.String field, int precisionStep, int? min, int? max, bool minInclusive, bool maxInclusive)
606  {
607  return new NumericRangeQuery<int>(field, precisionStep, 32, min, max, minInclusive, maxInclusive);
608  }
609 
610  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>int</c>
611  /// range using the default <c>precisionStep</c> <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4).
612  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
613  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
614  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
615  /// </summary>
616  public static NumericRangeQuery<int> NewIntRange(System.String field, int? min, int? max, bool minInclusive, bool maxInclusive)
617  {
618  return new NumericRangeQuery<int>(field, NumericUtils.PRECISION_STEP_DEFAULT, 32, min, max, minInclusive, maxInclusive);
619  }
620 
621  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>double</c>
622  /// range using the given <a href="#precisionStepDesc"><c>precisionStep</c></a>.
623  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
624  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
625  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
626  /// </summary>
627  public static NumericRangeQuery<double> NewDoubleRange(System.String field, int precisionStep, double? min, double? max, bool minInclusive, bool maxInclusive)
628  {
629  return new NumericRangeQuery<double>(field, precisionStep, 64, min, max, minInclusive, maxInclusive);
630  }
631 
632  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>double</c>
633  /// range using the default <c>precisionStep</c> <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4).
634  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
635  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
636  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
637  /// </summary>
638  public static NumericRangeQuery<double> NewDoubleRange(System.String field, double? min, double? max, bool minInclusive, bool maxInclusive)
639  {
640  return new NumericRangeQuery<double>(field, NumericUtils.PRECISION_STEP_DEFAULT, 64, min, max, minInclusive, maxInclusive);
641  }
642 
643  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>float</c>
644  /// range using the given <a href="#precisionStepDesc"><c>precisionStep</c></a>.
645  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
646  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
647  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
648  /// </summary>
649  public static NumericRangeQuery<float> NewFloatRange(System.String field, int precisionStep, float? min, float? max, bool minInclusive, bool maxInclusive)
650  {
651  return new NumericRangeQuery<float>(field, precisionStep, 32, min, max, minInclusive, maxInclusive);
652  }
653 
654  /// <summary> Factory that creates a <c>NumericRangeQuery</c>, that queries a <c>float</c>
655  /// range using the default <c>precisionStep</c> <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4).
656  /// You can have half-open ranges (which are in fact &lt;/&#8804; or &gt;/&#8805; queries)
657  /// by setting the min or max value to <c>null</c>. By setting inclusive to false, it will
658  /// match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
659  /// </summary>
660  public static NumericRangeQuery<float> NewFloatRange(System.String field, float? min, float? max, bool minInclusive, bool maxInclusive)
661  {
662  return new NumericRangeQuery<float>(field, NumericUtils.PRECISION_STEP_DEFAULT, 32, min, max, minInclusive, maxInclusive);
663  }
664  }
665 }