private AbstractField DoubleField(string field, double value) { var f = new NumericField(field, precisionStep, Field.Store.NO, true); f.SetOmitNorms(true); f.SetOmitTermFreqAndPositions(true); f.SetDoubleValue(value); return(f); }
protected static Document CloneDocument(Document luceneDoc) { var clonedDocument = new Document(); foreach (AbstractField field in luceneDoc.GetFields()) { var numericField = field as NumericField; if (numericField != null) { var clonedNumericField = new NumericField(numericField.Name, numericField.IsStored ? Field.Store.YES : Field.Store.NO, numericField.IsIndexed); var numericValue = numericField.NumericValue; if (numericValue is int) { clonedNumericField.SetIntValue((int)numericValue); } else if (numericValue is long) { clonedNumericField.SetLongValue((long)numericValue); } else if (numericValue is double) { clonedNumericField.SetDoubleValue((double)numericValue); } else if (numericValue is float) { clonedNumericField.SetFloatValue((float)numericValue); } clonedDocument.Add(clonedNumericField); } else { Field clonedField; if (field.IsBinary) { clonedField = new Field(field.Name, field.GetBinaryValue(), field.IsStored ? Field.Store.YES : Field.Store.NO); } else if (field.StringValue != null) { clonedField = new Field(field.Name, field.StringValue, field.IsStored ? Field.Store.YES : Field.Store.NO, field.IsIndexed ? Field.Index.ANALYZED_NO_NORMS : Field.Index.NOT_ANALYZED_NO_NORMS, field.IsTermVectorStored ? Field.TermVector.YES : Field.TermVector.NO); } else { //probably token stream, and we can't handle fields with token streams, so we skip this. continue; } clonedDocument.Add(clonedField); } } return(clonedDocument); }
public IFieldable CreateLuceneField(string fieldName, object fieldValue) { if (!Numeric) { return(new Field(fieldName, LuceneUtility.ToFieldStringValue(fieldValue), Store, Index) { Boost = Boost }); } var field = new NumericField(fieldName, Store, Index != Field.Index.NO) { Boost = Boost }; if (fieldValue is Int32) { field.SetIntValue((int)fieldValue); } else if (fieldValue is Int64) { field.SetLongValue((long)fieldValue); } else if (fieldValue is Single) { field.SetFloatValue((float)fieldValue); } else if (fieldValue is Double) { field.SetDoubleValue((double)fieldValue); } else if (fieldValue is Decimal) { field.SetDoubleValue((double)(decimal)fieldValue); } else { throw new NotSupportedException(); } return(field); }
private static Document CloneDocument(Document luceneDoc) { var clonedDocument = new Document(); foreach (AbstractField field in luceneDoc.GetFields()) { var numericField = field as NumericField; if (numericField != null) { var clonedNumericField = new NumericField(numericField.Name(), numericField.IsStored() ? Field.Store.YES : Field.Store.NO, numericField.IsIndexed()); var numericValue = numericField.GetNumericValue(); if (numericValue is int) { clonedNumericField.SetIntValue((int)numericValue); } else if (numericValue is long) { clonedNumericField.SetLongValue((long)numericValue); } else if (numericValue is double) { clonedNumericField.SetDoubleValue((double)numericValue); } else if (numericValue is float) { clonedNumericField.SetFloatValue((float)numericValue); } clonedDocument.Add(clonedNumericField); } else { Field clonedField; if (field.IsBinary()) { clonedField = new Field(field.Name(), field.BinaryValue(), field.IsStored() ? Field.Store.YES : Field.Store.NO); } else { clonedField = new Field(field.Name(), field.StringValue(), field.IsStored() ? Field.Store.YES : Field.Store.NO, field.IsIndexed() ? Field.Index.ANALYZED_NO_NORMS : Field.Index.NOT_ANALYZED_NO_NORMS); } clonedDocument.Add(clonedField); } } return(clonedDocument); }
/// <summary> /// 将T转换成doc /// </summary> /// <param name="model"></param> /// <param name="fieldModelList"></param> /// <returns></returns> private Document ParseModeltoDoc(T model, IEnumerable <FieldDataModel> fieldModelList) { Document document = new Document(); Type type = model.GetType(); foreach (var item in fieldModelList) { PropertyInfo propertyInfo = type.GetProperty(item.PropertyName); var propertyValue = propertyInfo.GetValue(model); if (propertyValue != null) { string valueString = propertyValue.ToString(); IFieldable fieldable = null; if (item.FieldType == TypeCode.String) { fieldable = new Field(item.FieldName, valueString, item.Store, item.Index, item.TermVector); } else { NumericField numericField = new NumericField(item.FieldName, item.Store, item.Index == Field.Index.ANALYZED_NO_NORMS); switch (item.FieldType) { case TypeCode.Double: numericField.SetDoubleValue(Convert.ToDouble(valueString)); break; case TypeCode.Single: numericField.SetFloatValue(Convert.ToSingle(valueString)); break; case TypeCode.Int32: numericField.SetIntValue(Convert.ToInt32(valueString)); break; case TypeCode.Int64: numericField.SetLongValue(Convert.ToInt64(valueString)); break; default: break; } fieldable = numericField; } document.Add(fieldable); } } return(document); }
public AbstractField[] CreateIndexableFields(Point point) { var f = new AbstractField[2]; var f0 = new NumericField(fieldNameX, precisionStep, Field.Store.NO, true); // {OmitNorms = true, OmitTermFreqAndPositions = true}; f0.SetOmitNorms(true); f0.SetOmitTermFreqAndPositions(true); f0.SetDoubleValue(point.GetX()); f[0] = f0; var f1 = new NumericField(fieldNameY, precisionStep, Field.Store.NO, true); //{OmitNorms = true, OmitTermFreqAndPositions = true}; f1.SetOmitNorms(true); f1.SetOmitTermFreqAndPositions(true); f1.SetDoubleValue(point.GetY()); f[1] = f1; return(f); }
internal static NumericField SetValue(this NumericField field, ValueType value) { if (value is int) { return(field.SetIntValue((int)value)); } if (value is long) { return(field.SetLongValue((long)value)); } if (value is double) { return(field.SetDoubleValue((double)value)); } if (value is float) { return(field.SetFloatValue((float)value)); } throw new ArgumentException("Unable to store ValueType " + value.GetType() + " as NumericField.", "value"); }
public Document CreateDocument(Place place) { var doc = new Document(); var ratingField = new NumericField(Schema.Rating, 2, Field.Store.YES, true); ratingField.SetDoubleValue(place.Rating); doc.Add(new Field(Schema.Id, place.Id, Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field(Schema.Name, true, place.Name, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); doc.Add(new Field(Schema.PlaceId, place.PlaceId, Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(ratingField); doc.Add(new Field(Schema.Vicinity, true, place.Vicinity, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); foreach (var type in place.Types) { doc.Add(new Field(Schema.Types, type, Field.Store.YES, Field.Index.ANALYZED)); } doc.Add(new Field(Schema.OpenNow, place.OpeningHours?.OpenNow.ToString() ?? string.Empty, Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field(Schema.Location, place.Geometry.Location.ToString(), Field.Store.YES, Field.Index.ANALYZED)); return(doc); }
/// <summary> /// 将对象转成Lucene里面的Document类型 /// </summary> /// <param name="obj"></param> /// <param name="columnFields"></param> /// <returns></returns> public static Document Convert(object obj, ColumnField[] columnFields) { Document document = null; if (obj != null) { document = new Document(); Type type = obj.GetType(); foreach (ColumnField columnField in columnFields) { if (columnField.IsCustomScore) {//为文档增加自定义评分列 NumericField numericField = new NumericField(columnField.Column, columnField.Store, true); numericField.SetIntValue(1); document.Add(numericField); columnField.Type = FieldType.INT32; continue; } Lucene.Net.Documents.Field.Store store = columnField.Store; string fieldName = columnField.Column; PropertyInfo propertyInfo = type.GetProperty(fieldName); if (propertyInfo != null) { object value = propertyInfo.GetValue(obj, null); if (value != null) { if (columnField.Index == Field.Index.ANALYZED ||//分词建索引 columnField.Index == Field.Index.ANALYZED_NO_NORMS) //分词建索引,不支持权重 { Field field = new Field(fieldName, value.ToString(), store, columnField.Index); field.Boost = columnField.Boost; document.Add(field); columnField.Type = FieldType.STRING; } else { string typeName = value.GetType().Name; if (typeName == FieldType.SINGLE) { NumericField numericField = new NumericField(fieldName, store, true); numericField.SetFloatValue(System.Convert.ToSingle(value)); numericField.Boost = columnField.Boost; document.Add(numericField); columnField.Type = FieldType.SINGLE; } else if (typeName == FieldType.DOUBLE || typeName == FieldType.DECIMAL) { NumericField numericField = new NumericField(fieldName, store, true); numericField.SetDoubleValue(System.Convert.ToDouble(value)); numericField.Boost = columnField.Boost; document.Add(numericField); columnField.Type = FieldType.DOUBLE; } else if (typeName == FieldType.INT32) { NumericField numericField = new NumericField(fieldName, store, true); numericField.SetIntValue(System.Convert.ToInt32(value)); numericField.Boost = columnField.Boost; document.Add(numericField); columnField.Type = FieldType.INT32; } else if (typeName == FieldType.INT64) { NumericField numericField = new NumericField(fieldName, store, true); numericField.SetLongValue(System.Convert.ToInt64(value)); numericField.Boost = columnField.Boost; document.Add(numericField); columnField.Type = FieldType.INT64; } else if (typeName == FieldType.DATETIME) { NumericField numericField = new NumericField(fieldName, store, true); DateTime dateTime = System.Convert.ToDateTime(value); numericField.SetLongValue(dateTime.Ticks); numericField.Boost = columnField.Boost; document.Add(numericField); columnField.Type = FieldType.DATETIME; } else { Field field = new Field(fieldName, value.ToString(), store, columnField.Index); field.Boost = columnField.Boost; document.Add(field); columnField.Type = FieldType.STRING; } } } } } } return(document); }
private static void CreateIndexContent() { using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(m_directoryPath), new NativeFSLockFactory())) //指定索引文件(打开索引目录) FS指的是就是FileSystem { bool isUpdate = IndexReader.IndexExists(directory); //IndexReader:对索引进行读取的类。该语句的作用:判断索引库文件夹是否存在以及索引特征文件是否存在。 if (isUpdate) { //同时只能有一段代码对索引库进行写操作。当使用IndexWriter打开directory时会自动对索引库文件上锁。 //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁(提示一下:如果我现在正在写着已经加锁了,但是还没有写完,这时候又来一个请求,那么不就解锁了吗?这个问题后面会解决) if (IndexWriter.IsLocked(directory)) { IndexWriter.Unlock(directory); } } using (IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, IndexWriter.MaxFieldLength.UNLIMITED)) //向索引库中写索引。这时在这里加锁。 { //如果队列中有数据,获取队列中的数据写到Lucene.Net中。 while (Queue.Count > 0) { KeyValuePair <T, LuceneTypeEnum> keyValuePair = Queue.Dequeue(); T model = keyValuePair.Key; Type type = model.GetType(); PropertyInfo propertyInfo = type.GetProperty(m_luceneDataModels[0].PropertyName); var propertyValue = propertyInfo.GetValue(model); string valueString = propertyValue != null?propertyValue.ToString() : null; writer.DeleteDocuments(new Term(m_luceneDataModels[0].FieldName, valueString)); //删除 if (keyValuePair.Value == LuceneTypeEnum.Delete) { continue; } //表示一篇文档。 Document document = new Document(); //Field.Store.YES:表示是否存储原值。只有当Field.Store.YES在后面才能用doc.Get("number")取出值来.Field.Index. NOT_ANALYZED:不进行分词保存 //Field.Index. ANALYZED:进行分词保存:也就是要进行全文的字段要设置分词 保存(因为要进行模糊查询 //Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS:不仅保存分词还保存分词的距离。 foreach (FieldDataModel item in m_luceneDataModels) { propertyInfo = type.GetProperty(item.PropertyName); propertyValue = propertyInfo.GetValue(model); if (propertyValue != null) { valueString = propertyValue.ToString(); IFieldable fieldable = null; if (item.FieldType == TypeCode.String) { fieldable = new Field(item.FieldName, valueString, item.Store, item.Index, item.TermVector); } else { NumericField numericField = new NumericField(item.FieldName, item.Store, item.Index == Field.Index.ANALYZED_NO_NORMS); switch (item.FieldType) { case TypeCode.Double: numericField.SetDoubleValue(Convert.ToDouble(valueString)); break; case TypeCode.Single: numericField.SetFloatValue(Convert.ToSingle(valueString)); break; case TypeCode.Int32: numericField.SetIntValue(Convert.ToInt32(valueString)); break; case TypeCode.Int64: numericField.SetLongValue(Convert.ToInt64(valueString)); break; default: break; } fieldable = numericField; } document.Add(fieldable); } } writer.AddDocument(document); } } //会自动解锁。 } }
/// <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)); } }
/// <summary> /// Adds the field to the lucene document. /// </summary> /// <param name="doc">The doc.</param> /// <param name="field">The field.</param> private static void AddFieldToDocument(ref Document doc, IDocumentField field) { if (field == null) { return; } var store = Field.Store.YES; var index = Field.Index.NOT_ANALYZED; if (field.ContainsAttribute(IndexStore.No)) { store = Field.Store.NO; } if (field.ContainsAttribute(IndexType.Analyzed)) { index = Field.Index.ANALYZED; } else if (field.ContainsAttribute(IndexType.No)) { index = Field.Index.NO; } if (field.Value == null) { return; } field.Name = field.Name.ToLower(); if (field.Name == "__key") { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); } } else if (field.Value is string) { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); doc.Add(new Field("_content", val.ToString(), Field.Store.NO, Field.Index.ANALYZED)); } } else if (field.Value is decimal) // parse prices { foreach (var val in field.Values) { var numericField = new NumericField(field.Name, store, index != Field.Index.NO); numericField.SetDoubleValue(double.Parse(val.ToString())); doc.Add(numericField); } } else if (field.Value is DateTime) // parse dates { foreach (var val in field.Values) { doc.Add( new Field( field.Name, DateTools.DateToString((DateTime)val, DateTools.Resolution.SECOND), store, index)); } } else // try detecting the type { // TODO: instead of auto detecting, use meta data information decimal t; if (Decimal.TryParse(field.Value.ToString(), out t)) { foreach (var val in field.Values) { var numericField = new NumericField(field.Name, store, index != Field.Index.NO); numericField.SetDoubleValue(double.Parse(val.ToString())); doc.Add(numericField); } } else { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); } } } }
protected virtual IList <IFieldable> ConvertToProviderFields(IndexDocumentField field) { // TODO: Introduce and use metadata describing value type var result = new List <IFieldable>(); var fieldName = LuceneSearchHelper.ToLuceneFieldName(field.Name); var store = field.IsRetrievable ? Field.Store.YES : Field.Store.NO; var index = field.IsSearchable ? Field.Index.ANALYZED : field.IsFilterable ? Field.Index.NOT_ANALYZED : Field.Index.NO; if (field.Value is string) { foreach (var value in field.Values) { result.Add(new Field(fieldName, (string)value, store, index)); if (field.IsSearchable) { result.Add(new Field(LuceneSearchHelper.SearchableFieldName, (string)value, Field.Store.NO, Field.Index.ANALYZED)); } } } else if (field.Value is bool) { var booleanFieldName = LuceneSearchHelper.GetBooleanFieldName(field.Name); foreach (var value in field.Values) { var stringValue = value.ToStringInvariant(); result.Add(new Field(fieldName, stringValue, store, index)); result.Add(new Field(booleanFieldName, stringValue, Field.Store.NO, Field.Index.NOT_ANALYZED)); } } else if (field.Value is DateTime) { var dateTimeFieldName = LuceneSearchHelper.GetDateTimeFieldName(field.Name); foreach (var value in field.Values) { var numericField = new NumericField(fieldName, store, index != Field.Index.NO); numericField.SetLongValue(((DateTime)value).Ticks); result.Add(numericField); result.Add(new Field(dateTimeFieldName, value.ToStringInvariant(), Field.Store.NO, Field.Index.NOT_ANALYZED)); } } else if (field.Value is GeoPoint) { var geoPoint = (GeoPoint)field.Value; result.Add(new Field(fieldName, geoPoint.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); var shape = _spatialContext.MakePoint(geoPoint.Longitude, geoPoint.Latitude); var strategy = new PointVectorStrategy(_spatialContext, fieldName); foreach (var f in strategy.CreateIndexableFields(shape)) { result.Add(f); } } else { double t; if (double.TryParse(field.Value.ToStringInvariant(), NumberStyles.Float, CultureInfo.InvariantCulture, out t)) { var facetableFieldName = LuceneSearchHelper.GetFacetableFieldName(field.Name); foreach (var value in field.Values) { var stringValue = value.ToStringInvariant(); var numericField = new NumericField(fieldName, store, index != Field.Index.NO); numericField.SetDoubleValue(double.Parse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture)); result.Add(numericField); result.Add(new Field(facetableFieldName, stringValue, Field.Store.NO, Field.Index.NOT_ANALYZED)); } } else { result.AddRange(field.Values.Select(value => new Field(fieldName, value.ToStringInvariant(), store, index))); } } return(result); }
/// <summary> /// Adds the field to the lucene document. /// </summary> /// <param name="doc">The doc.</param> /// <param name="field">The field.</param> private static void AddFieldToDocument(ref Document doc, IDocumentField field) { if (field == null) { return; } var store = Field.Store.YES; var index = Field.Index.NOT_ANALYZED; if (field.ContainsAttribute(value: IndexStore.NO)) { store = Field.Store.NO; } if (field.ContainsAttribute(IndexType.ANALYZED)) { index = Field.Index.ANALYZED; } else if (field.ContainsAttribute(IndexType.NO)) { index = Field.Index.NO; } if (field.Value == null) { return; } field.Name = field.Name.ToLower(); if (field.Name == "__key") { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); } } else if (field.Value is string) { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); doc.Add(new Field("_content", val.ToString(), Field.Store.NO, Field.Index.ANALYZED)); } } else if (field.Value is decimal) // parse prices { foreach (var val in field.Values) { var numericField = new NumericField(field.Name, store, index != Field.Index.NO); numericField.SetDoubleValue(double.Parse(val.ToString())); doc.Add(numericField); } } else if (field.Value is DateTime) // parse dates { foreach (var val in field.Values) { doc.Add( new Field( field.Name, DateTools.DateToString((DateTime)val, DateTools.Resolution.SECOND), store, index)); } } else // try detecting the type { // TODO: instead of auto detecting, use meta data information decimal t; if (Decimal.TryParse(field.Value.ToString(), out t)) { foreach (var val in field.Values) { var numericField = new NumericField(field.Name, store, index != Field.Index.NO); numericField.SetDoubleValue(double.Parse(val.ToString())); doc.Add(numericField); } } else { foreach (var val in field.Values) { doc.Add(new Field(field.Name, val.ToString(), store, index)); } } } }
/// <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 IEnumerable <AbstractField> CreateFields(string name, JToken value, Field.Store defaultStorage, Field.TermVector defaultTermVector) { if (name.IsNullOrWhiteSpace()) { throw new ArgumentException(@"Field must be not null, not empty and cannot contain whitespace", "name"); } var fieldIndexingOptions = m_indexDefinition.GetIndex(name, null); var storage = m_indexDefinition.GetStorage(name, defaultStorage); var termVector = m_indexDefinition.GetTermVector(name, defaultTermVector); 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 for analyzed and not analyzed. if (value.Type != JTokenType.Date && value.Type != JTokenType.TimeSpan) { yield return(new Field(name, value.ToString(), storage, m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } } else { switch (value.Type) { case JTokenType.Array: { //Add each item in the array as a field with the same name. //Return an _IsArray field. if (Equals(storage, Field.Store.NO) == false) { yield return(new Field(name + "_IsArray", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } var jArray = value as JArray; if (jArray == null) { throw new InvalidOperationException("Shouldn't Happen"); } foreach (var arrayValue in jArray) { if (CanCreateFieldsForNestedArray(arrayValue, fieldIndexingOptions) == false) { continue; } foreach (var field in CreateFields(name, arrayValue, storage, Field.TermVector.NO)) { yield return(field); } } break; } case JTokenType.Boolean: { yield return(new Field(name, (value.Value <bool>()) ? "true" : "false", storage, m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } break; case JTokenType.Bytes: { var bytes = value.Value <byte[]>(); if (bytes != null) { yield return(CreateBinaryField(name, bytes, storage, fieldIndexingOptions, termVector)); } } break; case JTokenType.Date: { var val = value.Value <DateTime>(); var dateAsString = val.ToString(Default.DateTimeFormatsToWrite); if (val.Kind == DateTimeKind.Utc) { dateAsString += "Z"; } yield return(new Field(name, dateAsString, storage, m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } break; case JTokenType.Guid: { yield return(new Field(name, value.Value <Guid>().ToString(), storage, m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } break; case JTokenType.None: case JTokenType.Null: { yield return(new Field(name, Constants.NullValue, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } break; case JTokenType.Object: { //Add an _IsObject field if (Equals(storage, Field.Store.NO) == false) { yield return(new Field(name + "_IsObject", "true", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); } //Recursively add properties on the object. foreach (var objectValue in value.Children <JProperty>()) { if (CanCreateFieldsForNestedObject(objectValue, fieldIndexingOptions) == false) { continue; } foreach (var field in CreateFields(name + "." + objectValue.Name, objectValue.Value, storage, defaultTermVector)) { yield return(field); } } } break; case JTokenType.String: { if (Equals(value.Value <string>(), string.Empty)) { yield return(new Field(name, Constants.EmptyString, storage, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); yield break; } var index = m_indexDefinition.GetIndex(name, Field.Index.ANALYZED); yield return(new Field(name, value.ToString(), storage, index, termVector)); } break; case JTokenType.Float: { var f = value.Value <float>(); var index = m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS); yield return(new Field(name, f.ToString(CultureInfo.InvariantCulture), storage, index, termVector)); var numericField = new NumericField(name + "_Range", storage, true); if (m_indexDefinition.GetSortOption(name) == SortOptions.Double) { yield return(numericField.SetDoubleValue(value.Value <double>())); } else { yield return(numericField.SetFloatValue(value.Value <float>())); } } break; case JTokenType.Integer: { var i = value.Value <int>(); var index = m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS); yield return(new Field(name, i.ToString(CultureInfo.InvariantCulture), storage, index, termVector)); var numericField = new NumericField(name + "_Range", storage, true); if (m_indexDefinition.GetSortOption(name) == SortOptions.Long) { yield return(numericField.SetLongValue(value.Value <long>())); } else { yield return(numericField.SetIntValue(value.Value <int>())); } } break; case JTokenType.TimeSpan: { var val = value.Value <TimeSpan>(); var index = m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS); yield return(new Field(name, val.ToString("c"), storage, index, termVector)); var numericField = new NumericField(name + "_Range", storage, true); yield return(numericField.SetLongValue(val.Ticks)); } break; case JTokenType.Uri: { yield return(new Field(name, value.Value <Uri>().ToString(), storage, m_indexDefinition.GetIndex(name, Field.Index.NOT_ANALYZED_NO_NORMS), termVector)); } break; case JTokenType.Undefined: case JTokenType.Raw: case JTokenType.Property: case JTokenType.Constructor: case JTokenType.Comment: //Do Nothing... break; default: throw new ArgumentOutOfRangeException("The specified JToken Type: " + value.Type + " is invalid or has not been implemented."); } } }
public static Document ToDocument(this SearchDocument content) { var doc = new Document(); doc.Add(new Field(SearchDocument.IdentifierKey, content.Identifier.ToString(), Field.Store.YES, Field.Index.NO)); doc.Add(new Field(SearchDocument.UserIdentifierKey, content.UserIdentifier.ToString(), Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field(SearchDocument.MemberNameKey, content.MemberName, Field.Store.YES, Field.Index.ANALYZED)); var typeField = new NumericField(SearchDocument.TypeKey, Field.Store.YES, true); typeField.SetIntValue((int)content.Type); doc.Add(typeField); var latField = new NumericField(SearchDocument.LatitudeKey, Field.Store.YES, true); latField.SetDoubleValue(content.Latitude); doc.Add(latField); var longField = new NumericField(SearchDocument.LongitudeKey, Field.Store.YES, true); longField.SetDoubleValue(content.Longitude); doc.Add(longField); doc.Add(new Field(SearchDocument.CreatedOnKey, content.CreatedOn.ToStringExact(), Field.Store.YES, Field.Index.NO)); var permissions = content.Permissions(); if (!string.IsNullOrWhiteSpace(permissions)) { doc.Add(new Field(SearchDocument.PermissionsKey, permissions, Field.Store.YES, Field.Index.NO)); } if (!string.IsNullOrWhiteSpace(content.ImageData)) { doc.Add(new Field(SearchDocument.ImageDataKey, content.ImageData, Field.Store.YES, Field.Index.NO)); } if (!string.IsNullOrWhiteSpace(content.Title)) { doc.Add(new Field(SearchDocument.TitleKey, content.Title, Field.Store.YES, Field.Index.NO)); } if (!string.IsNullOrWhiteSpace(content.Description)) { doc.Add(new Field(SearchDocument.DescriptionKey, content.Description, Field.Store.YES, Field.Index.NO)); } if (!string.IsNullOrWhiteSpace(content.Key)) { doc.Add(new Field(SearchDocument.KeyKey, content.Key, Field.Store.YES, Field.Index.NOT_ANALYZED)); } if (!string.IsNullOrWhiteSpace(content.Content)) { doc.Add(new Field(SearchDocument.ContentKey, content.Content, Field.Store.YES, Field.Index.ANALYZED)); } if (!string.IsNullOrWhiteSpace(content.Location)) { doc.Add(new Field(SearchDocument.LocationKey, content.Location, Field.Store.YES, Field.Index.ANALYZED)); } return(doc); }