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
NumericField.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.IO;
20 using Lucene.Net.Search;
21 using NumericTokenStream = Lucene.Net.Analysis.NumericTokenStream;
22 using TokenStream = Lucene.Net.Analysis.TokenStream;
23 using NumericUtils = Lucene.Net.Util.NumericUtils;
24 using FieldCache = Lucene.Net.Search.FieldCache;
25 using SortField = Lucene.Net.Search.SortField;
26 
27 namespace Lucene.Net.Documents
28 {
29  // javadocs
30 
31  /// <summary> <p/>This class provides a <see cref="Field" /> that enables indexing
32  /// of numeric values for efficient range filtering and
33  /// sorting. Here's an example usage, adding an int value:
34  /// <code>
35  /// document.add(new NumericField(name).setIntValue(value));
36  /// </code>
37  ///
38  /// For optimal performance, re-use the
39  /// <c>NumericField</c> and <see cref="Document" /> instance for more than
40  /// one document:
41  ///
42  /// <code>
43  /// NumericField field = new NumericField(name);
44  /// Document document = new Document();
45  /// document.add(field);
46  ///
47  /// for(all documents) {
48  /// ...
49  /// field.setIntValue(value)
50  /// writer.addDocument(document);
51  /// ...
52  /// }
53  /// </code>
54  ///
55  /// <p/>The .Net native types <c>int</c>, <c>long</c>,
56  /// <c>float</c> and <c>double</c> are
57  /// directly supported. However, any value that can be
58  /// converted into these native types can also be indexed.
59  /// For example, date/time values represented by a
60  /// <see cref="System.DateTime" /> can be translated into a long
61  /// value using the <c>java.util.Date.getTime</c> method. If you
62  /// don't need millisecond precision, you can quantize the
63  /// value, either by dividing the result of
64  /// <c>java.util.Date.getTime</c> or using the separate getters
65  /// (for year, month, etc.) to construct an <c>int</c> or
66  /// <c>long</c> value.<p/>
67  ///
68  /// <p/>To perform range querying or filtering against a
69  /// <c>NumericField</c>, use <see cref="NumericRangeQuery{T}" /> or <see cref="NumericRangeFilter{T}" />
70  ///. To sort according to a
71  /// <c>NumericField</c>, use the normal numeric sort types, eg
72  /// <see cref="SortField.INT" /> <c>NumericField</c> values
73  /// can also be loaded directly from <see cref="FieldCache" />.<p/>
74  ///
75  /// <p/>By default, a <c>NumericField</c>'s value is not stored but
76  /// is indexed for range filtering and sorting. You can use
77  /// the <see cref="NumericField(String,Field.Store,bool)" />
78  /// constructor if you need to change these defaults.<p/>
79  ///
80  /// <p/>You may add the same field name as a <c>NumericField</c> to
81  /// the same document more than once. Range querying and
82  /// filtering will be the logical OR of all values; so a range query
83  /// will hit all documents that have at least one value in
84  /// the range. However sort behavior is not defined. If you need to sort,
85  /// you should separately index a single-valued <c>NumericField</c>.<p/>
86  ///
87  /// <p/>A <c>NumericField</c> will consume somewhat more disk space
88  /// in the index than an ordinary single-valued field.
89  /// However, for a typical index that includes substantial
90  /// textual content per document, this increase will likely
91  /// be in the noise. <p/>
92  ///
93  /// <p/>Within Lucene, each numeric value is indexed as a
94  /// <em>trie</em> structure, where each term is logically
95  /// assigned to larger and larger pre-defined brackets (which
96  /// are simply lower-precision representations of the value).
97  /// The step size between each successive bracket is called the
98  /// <c>precisionStep</c>, measured in bits. Smaller
99  /// <c>precisionStep</c> values result in larger number
100  /// of brackets, which consumes more disk space in the index
101  /// but may result in faster range search performance. The
102  /// default value, 4, was selected for a reasonable tradeoff
103  /// of disk space consumption versus performance. You can
104  /// use the expert constructor <see cref="NumericField(String,int,Field.Store,bool)" />
105  /// if you'd
106  /// like to change the value. Note that you must also
107  /// specify a congruent value when creating <see cref="NumericRangeQuery{T}" />
108  /// or <see cref="NumericRangeFilter{T}" />.
109  /// For low cardinality fields larger precision steps are good.
110  /// If the cardinality is &lt; 100, it is fair
111  /// to use <see cref="int.MaxValue" />, which produces one
112  /// term per value.
113  ///
114  /// <p/>For more information on the internals of numeric trie
115  /// indexing, including the <a
116  /// href="../search/NumericRangeQuery.html#precisionStepDesc"><c>precisionStep</c></a>
117  /// configuration, see <see cref="NumericRangeQuery{T}" />. The format of
118  /// indexed values is described in <see cref="NumericUtils" />.
119  ///
120  /// <p/>If you only need to sort by numeric value, and never
121  /// run range querying/filtering, you can index using a
122  /// <c>precisionStep</c> of <see cref="int.MaxValue" />.
123  /// This will minimize disk space consumed. <p/>
124  ///
125  /// <p/>More advanced users can instead use <see cref="NumericTokenStream" />
126  /// directly, when indexing numbers. This
127  /// class is a wrapper around this token stream type for
128  /// easier, more intuitive usage.<p/>
129  ///
130  /// <p/><b>NOTE:</b> This class is only used during
131  /// indexing. When retrieving the stored field value from a
132  /// <see cref="Document" /> instance after search, you will get a
133  /// conventional <see cref="IFieldable" /> instance where the numeric
134  /// values are returned as <see cref="String" />s (according to
135  /// <c>toString(value)</c> of the used data type).
136  ///
137  /// <p/><font color="red"><b>NOTE:</b> This API is
138  /// experimental and might change in incompatible ways in the
139  /// next release.</font>
140  ///
141  /// </summary>
142  /// <since> 2.9
143  /// </since>
144  [Serializable]
145  public sealed class NumericField:AbstractField
146  {
147 
148  new private readonly NumericTokenStream tokenStream;
149 
150  /// <summary> Creates a field for numeric values using the default <c>precisionStep</c>
151  /// <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4). The instance is not yet initialized with
152  /// a numeric value, before indexing a document containing this field,
153  /// set a value using the various set<em>???</em>Value() methods.
154  /// This constructor creates an indexed, but not stored field.
155  /// </summary>
156  /// <param name="name">the field name
157  /// </param>
158  public NumericField(System.String name):this(name, NumericUtils.PRECISION_STEP_DEFAULT, Field.Store.NO, true)
159  {
160  }
161 
162  /// <summary> Creates a field for numeric values using the default <c>precisionStep</c>
163  /// <see cref="NumericUtils.PRECISION_STEP_DEFAULT" /> (4). The instance is not yet initialized with
164  /// a numeric value, before indexing a document containing this field,
165  /// set a value using the various set<em>???</em>Value() methods.
166  /// </summary>
167  /// <param name="name">the field name
168  /// </param>
169  /// <param name="store">if the field should be stored in plain text form
170  /// (according to <c>toString(value)</c> of the used data type)
171  /// </param>
172  /// <param name="index">if the field should be indexed using <see cref="NumericTokenStream" />
173  /// </param>
174  public NumericField(System.String name, Field.Store store, bool index):this(name, NumericUtils.PRECISION_STEP_DEFAULT, store, index)
175  {
176  }
177 
178  /// <summary> Creates a field for numeric values with the specified
179  /// <c>precisionStep</c>. The instance is not yet initialized with
180  /// a numeric value, before indexing a document containing this field,
181  /// set a value using the various set<em>???</em>Value() methods.
182  /// This constructor creates an indexed, but not stored field.
183  /// </summary>
184  /// <param name="name">the field name
185  /// </param>
186  /// <param name="precisionStep">the used <a href="../search/NumericRangeQuery.html#precisionStepDesc">precision step</a>
187  /// </param>
188  public NumericField(System.String name, int precisionStep):this(name, precisionStep, Field.Store.NO, true)
189  {
190  }
191 
192  /// <summary> Creates a field for numeric values with the specified
193  /// <c>precisionStep</c>. The instance is not yet initialized with
194  /// a numeric value, before indexing a document containing this field,
195  /// set a value using the various set<em>???</em>Value() methods.
196  /// </summary>
197  /// <param name="name">the field name
198  /// </param>
199  /// <param name="precisionStep">the used <a href="../search/NumericRangeQuery.html#precisionStepDesc">precision step</a>
200  /// </param>
201  /// <param name="store">if the field should be stored in plain text form
202  /// (according to <c>toString(value)</c> of the used data type)
203  /// </param>
204  /// <param name="index">if the field should be indexed using <see cref="NumericTokenStream" />
205  /// </param>
206  public NumericField(System.String name, int precisionStep, Field.Store store, bool index):base(name, store, index?Field.Index.ANALYZED_NO_NORMS:Field.Index.NO, Field.TermVector.NO)
207  {
208  OmitTermFreqAndPositions = true;
209  tokenStream = new NumericTokenStream(precisionStep);
210  }
211 
212  /// <summary>Returns a <see cref="NumericTokenStream" /> for indexing the numeric value. </summary>
213  public override TokenStream TokenStreamValue
214  {
215  get { return IsIndexed ? tokenStream : null; }
216  }
217 
218  /// <summary>Returns always <c>null</c> for numeric fields </summary>
219  public override byte[] GetBinaryValue(byte[] result)
220  {
221  return null;
222  }
223 
224  /// <summary>Returns always <c>null</c> for numeric fields </summary>
225  public override TextReader ReaderValue
226  {
227  get { return null; }
228  }
229 
230  /// <summary>Returns the numeric value as a string (how it is stored, when <see cref="Field.Store.YES" /> is chosen). </summary>
231  public override string StringValue
232  {
233  get { return (fieldsData == null) ? null : fieldsData.ToString(); }
234  }
235 
236  /// <summary>Returns the current numeric value as a subclass of <see cref="Number" />, <c>null</c> if not yet initialized. </summary>
237  public ValueType NumericValue
238  {
239  get { return (System.ValueType) fieldsData; }
240  }
241 
242  /// <summary> Initializes the field with the supplied <c>long</c> value.</summary>
243  /// <param name="value_Renamed">the numeric value
244  /// </param>
245  /// <returns> this instance, because of this you can use it the following way:
246  /// <c>document.add(new NumericField(name, precisionStep).SetLongValue(value))</c>
247  /// </returns>
248  public NumericField SetLongValue(long value_Renamed)
249  {
250  tokenStream.SetLongValue(value_Renamed);
251  fieldsData = value_Renamed;
252  return this;
253  }
254 
255  /// <summary> Initializes the field with the supplied <c>int</c> value.</summary>
256  /// <param name="value_Renamed">the numeric value
257  /// </param>
258  /// <returns> this instance, because of this you can use it the following way:
259  /// <c>document.add(new NumericField(name, precisionStep).setIntValue(value))</c>
260  /// </returns>
261  public NumericField SetIntValue(int value_Renamed)
262  {
263  tokenStream.SetIntValue(value_Renamed);
264  fieldsData = value_Renamed;
265  return this;
266  }
267 
268  /// <summary> Initializes the field with the supplied <c>double</c> value.</summary>
269  /// <param name="value_Renamed">the numeric value
270  /// </param>
271  /// <returns> this instance, because of this you can use it the following way:
272  /// <c>document.add(new NumericField(name, precisionStep).setDoubleValue(value))</c>
273  /// </returns>
274  public NumericField SetDoubleValue(double value_Renamed)
275  {
276  tokenStream.SetDoubleValue(value_Renamed);
277  fieldsData = value_Renamed;
278  return this;
279  }
280 
281  /// <summary> Initializes the field with the supplied <c>float</c> value.</summary>
282  /// <param name="value_Renamed">the numeric value
283  /// </param>
284  /// <returns> this instance, because of this you can use it the following way:
285  /// <c>document.add(new NumericField(name, precisionStep).setFloatValue(value))</c>
286  /// </returns>
287  public NumericField SetFloatValue(float value_Renamed)
288  {
289  tokenStream.SetFloatValue(value_Renamed);
290  fieldsData = value_Renamed;
291  return this;
292  }
293  }
294 }