Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        /// <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);
        }
Esempio n. 7
0
        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");
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 10
0
        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));
            }
        }
Esempio n. 12
0
        /// <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));
                    }
                }
            }
        }
Esempio n. 13
0
        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.");
                }
            }
        }
Esempio n. 16
0
        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);
        }