/// <summary> /// Detects numeric range terms and expands range expressions accordingly /// </summary> /// <param name="field"></param> /// <param name="lower"></param> /// <param name="upper"></param> /// <param name="inclusive"></param> /// <returns></returns> protected override Query GetRangeQuery(string field, string lower, string upper, bool inclusive) { if (lower == "NULL" || lower == "*") { lower = null; } if (upper == "NULL" || upper == "*") { upper = null; } if ((lower == null || !NumericRangeValue.IsMatch(lower)) && (upper == null || !NumericRangeValue.IsMatch(upper))) { return(NewRangeQuery(field, lower, upper, inclusive)); } var from = NumberUtil.StringToNumber(lower); var to = NumberUtil.StringToNumber(upper); TypeCode numericType; if (from != null) { numericType = Type.GetTypeCode(from.GetType()); } else if (to != null) { numericType = Type.GetTypeCode(to.GetType()); } else { numericType = TypeCode.Empty; } switch (numericType) { case TypeCode.Int32: { return(NumericRangeQuery.NewIntRange(field, (int)(from ?? Int32.MinValue), (int)(to ?? Int32.MaxValue), inclusive, inclusive)); } case TypeCode.Int64: { return(NumericRangeQuery.NewLongRange(field, (long)(from ?? Int64.MinValue), (long)(to ?? Int64.MaxValue), inclusive, inclusive)); } case TypeCode.Double: { return(NumericRangeQuery.NewDoubleRange(field, (double)(from ?? Double.MinValue), (double)(to ?? Double.MaxValue), inclusive, inclusive)); } case TypeCode.Single: { return(NumericRangeQuery.NewFloatRange(field, (float)(from ?? Single.MinValue), (float)(to ?? Single.MaxValue), inclusive, inclusive)); } default: { return(NewRangeQuery(field, lower, upper, inclusive)); } } }
/// <summary> /// This method generate the fields for indexing documents in lucene from the values. /// Given a name and a value, it has the following behavior: /// * If the value is null, create a single field with the supplied name with the unanalyzed value 'NULL_VALUE' /// * If the value is string or was set to not analyzed, create a single field with the supplied name /// * If the value is date, create a single field with millisecond precision with the supplied name /// * If the value is numeric (int, long, double, decimal, or float) will create two fields: /// 1. with the supplied name, containing the numeric value as an unanalyzed string - useful for direct queries /// 2. with the name: name +'_Range', containing the numeric value in a form that allows range queries /// </summary> private static IEnumerable <AbstractField> Createfields(string name, object value, IndexDefinition indexDefinition, Field.Store defaultStorage) { if (value == null) { yield return(new Field(name, "NULL_VALUE", indexDefinition.GetStorage(name, defaultStorage), Field.Index.NOT_ANALYZED)); yield break; } if (indexDefinition.GetIndex(name, Field.Index.ANALYZED) == Field.Index.NOT_ANALYZED || value is string) { yield return(new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.ANALYZED))); yield break; } if (value is DateTime) { yield return(new Field(name, DateTools.DateToString((DateTime)value, DateTools.Resolution.MILLISECOND), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } else if (value is IConvertible) // we need this to store numbers in invariant format, so JSON could read them { var convert = ((IConvertible)value); yield return(new Field(name, convert.ToString(CultureInfo.InvariantCulture), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, GetDefaultIndexOption(value)))); } else { yield return(new Field(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); yield return(new Field(name, JToken.FromObject(value).ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, GetDefaultIndexOption(value)))); } if (value is int) { yield return(new Field(name + "_Range", NumberUtil.NumberToString((int)value), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } if (value is long) { yield return(new Field(name + "_Range", NumberUtil.NumberToString((long)value), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } if (value is decimal) { yield return(new Field(name + "_Range", NumberUtil.NumberToString((double)(decimal)value), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } if (value is float) { yield return(new Field(name + "_Range", NumberUtil.NumberToString((float)value), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } if (value is double) { yield return(new Field(name + "_Range", NumberUtil.NumberToString((double)value), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } }