private IEnumerable <AbstractField> CreateNumericFieldWithCaching(string name, object value, Field.Store defaultStorage) { var fieldName = name + "_Range"; var storage = indexDefinition.GetStorage(name, defaultStorage); var cacheKey = new { fieldName, storage, multipleItemsSameFieldCountSum = multipleItemsSameFieldCount.Sum() }; NumericField numericField; if (numericFieldsCache.TryGetValue(cacheKey, out numericField) == false) { numericFieldsCache[cacheKey] = numericField = new NumericField(fieldName, storage, true); } if (value is int) { if (indexDefinition.GetSortOption(name) == SortOptions.Long) { yield return(numericField.SetLongValue((int)value)); } else { yield return(numericField.SetIntValue((int)value)); } } if (value is long) { yield return(numericField .SetLongValue((long)value)); } if (value is decimal) { yield return(numericField .SetDoubleValue((double)(decimal)value)); } if (value is float) { if (indexDefinition.GetSortOption(name) == SortOptions.Double) { yield return(numericField.SetDoubleValue((float)value)); } else { yield return(numericField.SetFloatValue((float)value)); } } if (value is double) { yield return(numericField .SetDoubleValue((double)value)); } }
public Lucene.Net.Search.SortField ToLuceneSortField(IndexDefinition definition) { var sortOptions = definition.GetSortOption(Field); if(sortOptions == null) return new Lucene.Net.Search.SortField(Field, CultureInfo.InvariantCulture, Descending); return new Lucene.Net.Search.SortField(Field, (int)sortOptions.Value); }
private IEnumerable <AbstractField> CreateRegularFields(string name, object value, Field.Store defaultStorage, bool nestedArray = false, Field.TermVector defaultTermVector = Field.TermVector.NO, Field.Index?analyzed = null) { var fieldIndexingOptions = analyzed ?? indexDefinition.GetIndex(name, null); var storage = indexDefinition.GetStorage(name, defaultStorage); var termVector = indexDefinition.GetTermVector(name, defaultTermVector); if (fieldIndexingOptions == Field.Index.NO && storage == Field.Store.NO && termVector == Field.TermVector.NO) { yield break; } if (fieldIndexingOptions == Field.Index.NO && storage == Field.Store.NO) { fieldIndexingOptions = Field.Index.ANALYZED; // we have some sort of term vector, forcing index to be analyzed, then. } if (value == null) { yield return(CreateFieldWithCaching(name, Constants.NullValue, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield break; } CheckIfSortOptionsAndInputTypeMatch(name, value); var attachmentFoIndexing = value as AttachmentForIndexing; if (attachmentFoIndexing != null) { if (database == null) { throw new InvalidOperationException( "Cannot use attachment for indexing if the database parameter is null. This is probably a RavenDB bug"); } var attachment = database.Attachments.GetStatic(attachmentFoIndexing.Key); if (attachment == null) { yield break; } var fieldWithCaching = CreateFieldWithCaching(name, string.Empty, Field.Store.NO, fieldIndexingOptions, termVector); if (database.TransactionalStorage.IsAlreadyInBatch) { var streamReader = new StreamReader(attachment.Data()); fieldWithCaching.SetValue(streamReader); } else { // we are not in batch operation so we have to create it be able to read attachment's data database.TransactionalStorage.Batch(accessor => { var streamReader = new StreamReader(attachment.Data()); // we have to read it into memory because we after exiting the batch an attachment's data stream will be closed fieldWithCaching.SetValue(streamReader.ReadToEnd()); }); } yield return(fieldWithCaching); yield break; } if (Equals(value, string.Empty)) { yield return(CreateFieldWithCaching(name, Constants.EmptyString, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield break; } var dynamicNullObject = value as DynamicNullObject; if (ReferenceEquals(dynamicNullObject, null) == false) { if (dynamicNullObject.IsExplicitNull) { var sortOptions = indexDefinition.GetSortOption(name, query: null); if (sortOptions == null || sortOptions.Value == SortOptions.String || sortOptions.Value == SortOptions.None || sortOptions.Value == SortOptions.StringVal || sortOptions.Value == SortOptions.Custom) { yield return(CreateFieldWithCaching(name, Constants.NullValue, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } foreach (var field in CreateNumericFieldWithCaching(name, GetNullValueForSorting(sortOptions), storage, termVector)) { yield return(field); } } yield break; } var boostedValue = value as BoostedValue; if (boostedValue != null) { foreach (var field in CreateFields(name, boostedValue.Value, storage, false, termVector)) { field.Boost = boostedValue.Boost; field.OmitNorms = false; yield return(field); } yield break; } var abstractField = value as AbstractField; if (abstractField != null) { yield return(abstractField); yield break; } var bytes = value as byte[]; if (bytes != null) { yield return(CreateBinaryFieldWithCaching(name, bytes, storage, fieldIndexingOptions, termVector)); yield break; } var itemsToIndex = value as IEnumerable; if (itemsToIndex != null && ShouldTreatAsEnumerable(itemsToIndex)) { int count = 1; if (nestedArray == false) { yield return(new Field(name + "_IsArray", "true", storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } foreach (var itemToIndex in itemsToIndex) { if (!CanCreateFieldsForNestedArray(itemToIndex, fieldIndexingOptions)) { continue; } multipleItemsSameFieldCount.Add(count++); foreach (var field in CreateFields(name, itemToIndex, storage, nestedArray: true, defaultTermVector: defaultTermVector, analyzed: analyzed)) { yield return(field); } multipleItemsSameFieldCount.RemoveAt(multipleItemsSameFieldCount.Count - 1); } yield break; } if (Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED) || Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED_NO_NORMS))// explicitly not analyzed { // date time, time span and date time offset have the same structure fo analyzed and not analyzed. if (!(value is DateTime) && !(value is DateTimeOffset) && !(value is TimeSpan)) { yield return(CreateFieldWithCaching(name, value.ToString(), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); yield break; } } if (value is string) { var index = indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return(CreateFieldWithCaching(name, value.ToString(), storage, index, termVector)); yield break; } if (value is TimeSpan) { var val = (TimeSpan)value; yield return(CreateFieldWithCaching(name, val.ToString("c", CultureInfo.InvariantCulture), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is DateTime) { var val = (DateTime)value; var dateAsString = val.GetDefaultRavenFormat(); if (val.Kind == DateTimeKind.Utc) { dateAsString += "Z"; } yield return(CreateFieldWithCaching(name, dateAsString, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is DateTimeOffset) { var val = (DateTimeOffset)value; string dtoStr; if (Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED) || Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED_NO_NORMS)) { dtoStr = val.ToString(Default.DateTimeOffsetFormatsToWrite, CultureInfo.InvariantCulture); } else { dtoStr = val.UtcDateTime.GetDefaultRavenFormat(true); } yield return(CreateFieldWithCaching(name, dtoStr, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is bool) { yield return(new Field(name, ((bool)value) ? "true" : "false", storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is double) { var d = (double)value; yield return(CreateFieldWithCaching(name, d.ToString("r", CultureInfo.InvariantCulture), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is decimal) { var d = (decimal)value; var s = d.ToString(CultureInfo.InvariantCulture); if (s.Contains('.')) { s = s.TrimEnd('0'); if (s.EndsWith(".")) { s = s.Substring(0, s.Length - 1); } } yield return(CreateFieldWithCaching(name, s, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is Enum) { yield return(CreateFieldWithCaching(name, value.ToString(), storage, indexDefinition.GetIndex(name, Field.Index.ANALYZED_NO_NORMS), termVector)); } 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(CreateFieldWithCaching(name, convert.ToString(CultureInfo.InvariantCulture), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is IDynamicJsonObject) { var inner = ((IDynamicJsonObject)value).Inner; yield return(CreateFieldWithCaching(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield return(CreateFieldWithCaching(name, inner.ToString(Formatting.None), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else { var jsonVal = RavenJToken.FromObject(value).ToString(Formatting.None); if (jsonVal.StartsWith("{") || jsonVal.StartsWith("[")) { yield return(CreateFieldWithCaching(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } else if (jsonVal.StartsWith("\"") && jsonVal.EndsWith("\"") && jsonVal.Length > 1) { jsonVal = jsonVal.Substring(1, jsonVal.Length - 2); } yield return(CreateFieldWithCaching(name, jsonVal, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } foreach (var numericField in CreateNumericFieldWithCaching(name, value, storage, termVector)) { yield return(numericField); } }
/// <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 enumerable, index all the items in the enumerable under the same field name /// * 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(string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Field must be not null, not empty and cannot contain whitespace", "name"); if (char.IsLetter(name[0]) == false && name[0] != '_') { name = "_" + name; } if (value == null) { yield return new Field(name, Constants.NullValue, indexDefinition.GetStorage(name, defaultStorage), Field.Index.NOT_ANALYZED); yield break; } if (value is DynamicNullObject) { if(((DynamicNullObject)value ).IsExplicitNull) { yield return new Field(name, Constants.NullValue, indexDefinition.GetStorage(name, defaultStorage), Field.Index.NOT_ANALYZED); } yield break; } if(value is AbstractField) { yield return (AbstractField)value; yield break; } var itemsToIndex = value as IEnumerable; if( itemsToIndex != null && ShouldTreatAsEnumerable(itemsToIndex)) { yield return new Field(name + "_IsArray", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); foreach (var itemToIndex in itemsToIndex) { foreach (var field in CreateFields(name, itemToIndex, indexDefinition, defaultStorage)) { yield return field; } } yield break; } if (indexDefinition.GetIndex(name, null) == Field.Index.NOT_ANALYZED)// explicitly not analyzed { yield return new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED)); yield break; } if (value is string) { var index = indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), index); 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 bool) { yield return new Field(name, ((bool) value) ? "true" : "false", 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, Field.Index.NOT_ANALYZED)); } else if (value is DynamicJsonObject) { var inner = ((DynamicJsonObject)value).Inner; yield return new Field(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); yield return new Field(name, inner.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED)); } 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, Field.Index.NOT_ANALYZED)); } var numericField = new NumericField(name + "_Range", indexDefinition.GetStorage(name, defaultStorage), true); if (value is int) { if(indexDefinition.GetSortOption(name) == SortOptions.Long) yield return numericField.SetLongValue((int)value); else yield return numericField.SetIntValue((int)value); } if (value is long) { yield return numericField .SetLongValue((long) value); } if (value is decimal) { yield return numericField .SetDoubleValue((double)(decimal)value); } if (value is float) { if (indexDefinition.GetSortOption(name) == SortOptions.Double) yield return numericField.SetDoubleValue((float)value); else yield return numericField.SetFloatValue((float) value); } if (value is double) { yield return numericField .SetDoubleValue((double)value); } }
/// <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 enumerable, index all the items in the enumerable under the same field name /// * 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> public IEnumerable <AbstractField> CreateFields(string name, object value, Field.Store defaultStorage, bool nestedArray = false, Field.TermVector defaultTermVector = Field.TermVector.NO) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Field must be not null, not empty and cannot contain whitespace", "name"); } if (char.IsLetter(name[0]) == false && name[0] != '_') { name = "_" + name; } var fieldIndexingOptions = indexDefinition.GetIndex(name, null); var storage = indexDefinition.GetStorage(name, defaultStorage); var termVector = indexDefinition.GetTermVector(name, defaultTermVector); if (value == null) { yield return(CreateFieldWithCaching(name, Constants.NullValue, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield break; } if (Equals(value, string.Empty)) { yield return(CreateFieldWithCaching(name, Constants.EmptyString, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield break; } if (value is DynamicNullObject) { if (((DynamicNullObject)value).IsExplicitNull) { var sortOptions = indexDefinition.GetSortOption(name); if (sortOptions != null && sortOptions.Value != SortOptions.None) { yield break; // we don't emit null for sorting } yield return(CreateFieldWithCaching(name, Constants.NullValue, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } yield break; } var boostedValue = value as BoostedValue; if (boostedValue != null) { foreach (var field in CreateFields(name, boostedValue.Value, storage, false, termVector)) { field.Boost = boostedValue.Boost; field.OmitNorms = false; yield return(field); } yield break; } var abstractField = value as AbstractField; if (abstractField != null) { yield return(abstractField); yield break; } var bytes = value as byte[]; if (bytes != null) { yield return(CreateBinaryFieldWithCaching(name, bytes, storage, fieldIndexingOptions, termVector)); yield break; } var itemsToIndex = value as IEnumerable; if (itemsToIndex != null && ShouldTreatAsEnumerable(itemsToIndex)) { var sentArrayField = false; int count = 1; foreach (var itemToIndex in itemsToIndex) { if (nestedArray == false && !Equals(storage, Field.Store.NO) && sentArrayField == false) { sentArrayField = true; yield return(new Field(name + "_IsArray", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } if (CanCreateFieldsForNestedArray(itemToIndex, fieldIndexingOptions)) { multipleItemsSameFieldCount.Add(count++); foreach (var field in CreateFields(name, itemToIndex, storage, nestedArray: true)) { yield return(field); } multipleItemsSameFieldCount.RemoveAt(multipleItemsSameFieldCount.Count - 1); } } yield break; } if (Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED) || Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED_NO_NORMS)) // explicitly not analyzed { // date time, time span and date time offset have the same structure fo analyzed and not analyzed. if (!(value is DateTime) && !(value is DateTimeOffset) && !(value is TimeSpan)) { yield return(CreateFieldWithCaching(name, value.ToString(), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); yield break; } } if (value is string) { var index = indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return(CreateFieldWithCaching(name, value.ToString(), storage, index, termVector)); yield break; } if (value is TimeSpan) { var val = (TimeSpan)value; yield return(CreateFieldWithCaching(name, val.ToString("c", CultureInfo.InvariantCulture), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is DateTime) { var val = (DateTime)value; var dateAsString = val.ToString(Default.DateTimeFormatsToWrite); if (val.Kind == DateTimeKind.Utc) { dateAsString += "Z"; } yield return(CreateFieldWithCaching(name, dateAsString, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is DateTimeOffset) { var val = (DateTimeOffset)value; string dtoStr; if (Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED) || Equals(fieldIndexingOptions, Field.Index.NOT_ANALYZED_NO_NORMS)) { dtoStr = val.ToString(Default.DateTimeOffsetFormatsToWrite); } else { dtoStr = val.UtcDateTime.ToString(Default.DateTimeFormatsToWrite) + "Z"; } yield return(CreateFieldWithCaching(name, dtoStr, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is bool) { yield return(new Field(name, ((bool)value) ? "true" : "false", storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is decimal) { var d = (decimal)value; var s = d.ToString(CultureInfo.InvariantCulture); if (s.Contains('.')) { s = s.TrimEnd('0'); if (s.EndsWith(".")) { s = s.Substring(0, s.Length - 1); } } yield return(CreateFieldWithCaching(name, s, storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } 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(CreateFieldWithCaching(name, convert.ToString(CultureInfo.InvariantCulture), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else if (value is IDynamicJsonObject) { var inner = ((IDynamicJsonObject)value).Inner; yield return(CreateFieldWithCaching(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield return(CreateFieldWithCaching(name, inner.ToString(Formatting.None), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } else { yield return(CreateFieldWithCaching(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield return(CreateFieldWithCaching(name, RavenJToken.FromObject(value).ToString(Formatting.None), storage, indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } foreach (var numericField in CreateNumericFieldWithCaching(name, value, storage, termVector)) { yield return(numericField); } }
/// <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; } var fields = value as IEnumerable<AbstractField>; if(fields != null) { foreach (var field in fields) { yield return field; } yield break; } if (indexDefinition.GetIndex(name, null) == Field.Index.NOT_ANALYZED)// explicitly not analyzed { yield return new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED)); yield break; } if (value is string) { var index = indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), index); 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 bool) { yield return new Field(name, ((bool) value) ? "true" : "false", 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, Field.Index.NOT_ANALYZED)); } else if (value is DynamicJsonObject) { var inner = ((DynamicJsonObject)value).Inner; yield return new Field(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); yield return new Field(name, inner.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED)); } 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, Field.Index.NOT_ANALYZED)); } var numericField = new NumericField(name + "_Range", indexDefinition.GetStorage(name, defaultStorage), true); if (value is int) { if(indexDefinition.GetSortOption(name) == SortOptions.Long) yield return numericField.SetLongValue((int)value); else yield return numericField.SetIntValue((int)value); } if (value is long) { yield return numericField .SetLongValue((long) value); } if (value is decimal) { yield return numericField .SetDoubleValue((double)(decimal)value); } if (value is float) { if (indexDefinition.GetSortOption(name) == SortOptions.Double) yield return numericField.SetDoubleValue((float)value); else yield return numericField.SetFloatValue((float) value); } if (value is double) { yield return numericField .SetDoubleValue((double)value); } }
/// <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 enumerable, index all the items in the enumerable under the same field name /// * 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 (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Field must be not null, not empty and cannot contain whitespace", "name"); } if (char.IsLetter(name[0]) == false && name[0] != '_') { name = "_" + name; } if (value == null) { yield return(new Field(name, "NULL_VALUE", indexDefinition.GetStorage(name, defaultStorage), Field.Index.NOT_ANALYZED)); yield break; } if (value is DynamicNullObject) { if (((DynamicNullObject)value).IsExplicitNull) { yield return(new Field(name, "NULL_VALUE", indexDefinition.GetStorage(name, defaultStorage), Field.Index.NOT_ANALYZED)); } yield break; } if (value is AbstractField) { yield return((AbstractField)value); yield break; } var itemsToIndex = value as IEnumerable; if (itemsToIndex != null && ShouldTreatAsEnumerable(itemsToIndex)) { yield return(new Field(name + "_IsArray", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); foreach (var itemToIndex in itemsToIndex) { foreach (var field in CreateFields(name, itemToIndex, indexDefinition, defaultStorage)) { yield return(field); } } yield break; } if (indexDefinition.GetIndex(name, null) == Field.Index.NOT_ANALYZED)// explicitly not analyzed { yield return(new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); yield break; } if (value is string) { var index = indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return(new Field(name, value.ToString(), indexDefinition.GetStorage(name, defaultStorage), index)); 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 bool) { yield return(new Field(name, ((bool)value) ? "true" : "false", 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, Field.Index.NOT_ANALYZED))); } else if (value is DynamicJsonObject) { var inner = ((DynamicJsonObject)value).Inner; yield return(new Field(name + "_ConvertToJson", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); yield return(new Field(name, inner.ToString(), indexDefinition.GetStorage(name, defaultStorage), indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED))); } 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, Field.Index.NOT_ANALYZED))); } var numericField = new NumericField(name + "_Range", indexDefinition.GetStorage(name, defaultStorage), true); if (value is int) { if (indexDefinition.GetSortOption(name) == SortOptions.Long) { yield return(numericField.SetLongValue((int)value)); } else { yield return(numericField.SetIntValue((int)value)); } } if (value is long) { yield return(numericField .SetLongValue((long)value)); } if (value is decimal) { yield return(numericField .SetDoubleValue((double)(decimal)value)); } if (value is float) { if (indexDefinition.GetSortOption(name) == SortOptions.Double) { yield return(numericField.SetDoubleValue((float)value)); } else { yield return(numericField.SetFloatValue((float)value)); } } if (value is double) { yield return(numericField .SetDoubleValue((double)value)); } }