//@ParametersFactory
        public static IList <Object[]> Parameters()
        {
            List <Object[]> ctorArgs = new List <object[]>();

            SpatialContext    ctx = SpatialContext.GEO;
            SpatialPrefixTree grid;
            SpatialStrategy   strategy;

            grid     = new GeohashPrefixTree(ctx, 12);
            strategy = new RecursivePrefixTreeStrategy(grid, "recursive_geohash");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            grid     = new QuadPrefixTree(ctx, 25);
            strategy = new RecursivePrefixTreeStrategy(grid, "recursive_quad");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            grid     = new GeohashPrefixTree(ctx, 12);
            strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            strategy = new PointVectorStrategy(ctx, "pointvector");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            return(ctorArgs);
        }
Exemple #2
0
 public RecursivePrefixTreeStrategyDistanceCustomScoreQuery(Query subQuery, RecursivePrefixTreeStrategy strategy, Point origin, String shapeField)
     : base(subQuery)
 {
     _strategy      = strategy;
     _origin        = origin;
     _cacheProvider = new PointPrefixTreeFieldCacheProvider(_strategy.GetGrid(), shapeField, 255);
 }
Exemple #3
0
        static void Main(string[] args)
        {
            const Version version = Lucene.Net.Util.Version.LUCENE_30;

            Directory dir      = new RAMDirectory();
            Analyzer  analyzer = new StandardAnalyzer(version);

            var indexWriter = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.UNLIMITED);

            SpatialContext ctx = SpatialContext.GEO;

            // BBoxStrategy
            //var strategy = new BBoxStrategy(ctx, "spartial"); // Can only index and search by retangle

            // TermQueryPrefixTreeStrategy
            //SpatialPrefixTree grid = new GeohashPrefixTree(ctx, 8);
            //var strategy = new TermQueryPrefixTreeStrategy(grid, "spartial"); // Only supports SpatialOperation.Intersects

            // RecursivePrefixTreeStrategy
            SpatialPrefixTree grid = new GeohashPrefixTree(ctx, 8);
            var strategy           = new RecursivePrefixTreeStrategy(grid, "spartial");



            // PointVectorStrategy
            //var strategy = new PointVectorStrategy(ctx, "pointvector");

            foreach (var doc in CreateDocuments(strategy))
            {
                indexWriter.AddDocument(doc);
            }
            indexWriter.Commit();
            indexWriter.Dispose();


            var searcher = new IndexSearcher(dir, true);

            Point littleMermaid = ctx.MakePoint(12.599239, 55.692848);



            // PointVectorStrategy
            //TopDocs hits = DistanceQueryAndSort_PointVectorStrategy(searcher, strategy, littleMermaid);
            //TopDocs hits = DistanceFilter_PointVectorStrategy(searcher, strategy, littleMermaid);
            //TopDocs hits = DistranceScore_PointVectorStrategy(searcher, strategy, littleMermaid);

            // TermQueryPrefixTreeStrategy
            //TopDocs hits = DistanceFilter_TermQueryPrefixTreeStrategy(searcher, strategy, littleMermaid);

            // RecursivePrefixTreeStrategy
            TopDocs hits = DistanceFilter_RecursivePrefixTreeStrategy(searcher, strategy, littleMermaid);

            Console.WriteLine("Found {0} document(s) that matched query:", hits.TotalHits);
            foreach (ScoreDoc match in hits.ScoreDocs)
            {
                Document doc = searcher.Doc(match.Doc);
                Console.WriteLine("Matched {0} (score: {1})", doc.Get("id"), match.Score);
            }
            searcher.Dispose();
        }
        public Filter ToFilter(SpatialContext spatialContext, SpatialPrefixTree tree)
        {
            var strategy = new RecursivePrefixTreeStrategy(tree, GeoFieldName);

            var spatialArgs = new SpatialArgs(SpatialOperation.Intersects,
                                              spatialContext.MakeRectangle(this.MinX, this.MaxX, this.MinY, this.MaxY));

            return(strategy.MakeFilter(spatialArgs));
        }
Exemple #5
0
        public Filter ToFilter(SpatialContext spatialContext, SpatialPrefixTree tree)
        {
            var strategy = new RecursivePrefixTreeStrategy(tree, GeoFieldName);

            var spatialArgs = new SpatialArgs(SpatialOperation.Intersects,
                                              spatialContext.MakeCircle(X, Y, DistanceUtils.Dist2Degrees(this.Distance, DistanceUtils.EARTH_MEAN_RADIUS_KM)));

            return(strategy.MakeFilter(spatialArgs));
        }
        public Filter ToFilter(SpatialContext spatialContext, SpatialPrefixTree tree)
        {
            var strategy = new RecursivePrefixTreeStrategy(tree, GeoFieldName);

            var spatialArgs = new SpatialArgs(SpatialOperation.Intersects,
                                              spatialContext.MakeBufferedLineString(
                                                  this.Points.Select(p => (IPoint) new Point(p[0], p[1], spatialContext)).ToList(),
                                                  DistanceUtils.Dist2Degrees(this.Distance, DistanceUtils.EARTH_MEAN_RADIUS_KM)));

            return(strategy.MakeFilter(spatialArgs));
        }
        public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter)
        {
            if (type != "geo_bounding_box")
            {
                return(null);
            }

            if (!(toFilter is BooleanQuery booleanQuery))
            {
                return(null);
            }

            var queryObj = filter as JObject;
            var first    = queryObj.Properties().First();

            var ctx = SpatialContext.Geo;

            var maxLevels = 11; //results in sub-meter precision for geohash

            //  This can also be constructed from SpatialPrefixTreeFactory
            SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);

            var geoPropertyName = first.Name;
            var strategy        = new RecursivePrefixTreeStrategy(grid, geoPropertyName);

            var boundingBox = (JObject)first.Value;

            var topLeftProperty     = boundingBox["top_left"] as JObject;
            var bottomRightProperty = boundingBox["bottom_right"] as JObject;

            if (topLeftProperty == null || bottomRightProperty == null)
            {
                return(null);
            }

            var left   = topLeftProperty["lon"];
            var top    = topLeftProperty["lat"];
            var bottom = bottomRightProperty["lat"];
            var right  = bottomRightProperty["lon"];

            var rectangle = ctx.MakeRectangle((double)left, (double)right, (double)bottom, (double)top);

            var args = new SpatialArgs(SpatialOperation.Intersects, rectangle);

            var spatialQuery      = strategy.MakeQuery(args);
            var valueSource       = strategy.MakeRecipDistanceValueSource(rectangle);
            var valueSourceFilter = new ValueSourceFilter(new QueryWrapperFilter(spatialQuery), valueSource, 0, 1);

            booleanQuery.Add(new FunctionQuery(valueSource), Occur.MUST);

            return(new FilteredQuery(booleanQuery, valueSourceFilter));
        }
        private static List <IFieldable> AddBounds(SpatialContext ctx, double lng, double lat)
        {
            SpatialPrefixTree grid        = new GeohashPrefixTree(ctx, 11);
            var strategy                  = new RecursivePrefixTreeStrategy(grid, Sitecore.ContentSearch.Spatial.Common.Constants.LocationFieldName);
            List <IFieldable> pointFields = new List <IFieldable>();
            Point             shape       = ctx.MakePoint(lng, lat);

            foreach (var f in strategy.CreateIndexableFields(shape))
            {
                if (f != null)
                {
                    pointFields.Add(f);
                }
            }
            return(pointFields);
        }
Exemple #9
0
        private QueryHelper <TModel> GeoFilter(Expression <Func <TModel, object> > exp, double longitude, double latitude, double distDEG)
        {
            string name = getName(exp.Body.ToString());
            //name = name.IndexOf('.') > -1 ? name.Substring(0, name.LastIndexOf('.')) : name;
            SpatialOperation op = SpatialOperation.Intersects;
            //SpatialStrategy strat = new PointVectorStrategy(ctx, name);
            int maxLevels          = 11;
            SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
            var strat = new RecursivePrefixTreeStrategy(grid, name);

            var point = ctx.MakePoint(longitude, latitude);
            var shape = ctx.MakeCircle(point, distDEG);
            var args  = new SpatialArgs(op, shape);

            filter = strat.MakeFilter(args);
            return(this);
        }
        public void Document_Writing_To_Index_Spatial_Data_And_Search_On_100km_Radius_RecursivePrefixTreeStrategy()
        {
            // NOTE: It is advised to use RecursivePrefixTreeStrategy, see:
            // https://stackoverflow.com/a/13631289/694494
            // Here's the Java sample code
            // https://github.com/apache/lucene-solr/blob/branch_4x/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java

            SpatialContext              ctx       = SpatialContext.GEO;
            int                         maxLevels = 11; //results in sub-meter precision for geohash
            SpatialPrefixTree           grid      = new GeohashPrefixTree(ctx, maxLevels);
            RecursivePrefixTreeStrategy strategy  = new RecursivePrefixTreeStrategy(grid, GeoLocationFieldName);

            // NOTE: The SpatialExample uses MatchAllDocsQuery however the strategy can create a query too, the source is here:
            // https://github.com/apache/lucenenet/blob/master/src/Lucene.Net.Spatial/SpatialStrategy.cs#L124
            // all that really does it take the filter created and creates a ConstantScoreQuery with it
            // which probably makes sense because a 'Score' for a geo coord doesn't make a lot of sense.
            RunTest(ctx, strategy, a => strategy.MakeQuery(a));
        }
Exemple #11
0
        public void CreateSpatialFilterAndWeight(PointRadiusCriterion geoFilter, Filter currentFilter, Weight currentWeight)
        {
            var spatialContext = SpatialContext.GEO;
            var geohashTree    = new GeohashPrefixTree(spatialContext, 10);
            var strategy       = new RecursivePrefixTreeStrategy(geohashTree, geoFilter.FieldName);
            var point          = spatialContext.MakePoint(geoFilter.Longitude, geoFilter.Latitude);

            var spatialArgs = new SpatialArgs(SpatialOperation.Intersects, spatialContext.MakeCircle(point,
                                                                                                     DistanceUtils.Dist2Degrees(geoFilter.RadiusKm, DistanceUtils.EARTH_MEAN_RADIUS_KM)));

            var circle = spatialContext.MakeCircle(point,
                                                   DistanceUtils.Dist2Degrees(geoFilter.RadiusKm, DistanceUtils.EARTH_MEAN_RADIUS_KM));
            var circleCells = strategy.GetGrid().GetWorldNode().GetSubCells(circle);

            var luceneFilters = new List <Filter>();

            if (currentFilter != null)
            {
                luceneFilters.Add(currentFilter);
            }

            var tempSpatial = strategy.MakeFilter(spatialArgs);

            luceneFilters.Add(tempSpatial);

            if (geoFilter.Sort != PointRadiusCriterion.SortOption.None)
            {
                var valueSource = strategy.MakeDistanceValueSource(point);
                var funcQ       = new FunctionQuery(valueSource);
                // this is a bit odd... but boosting the score negatively orders results
                if (geoFilter.Sort == PointRadiusCriterion.SortOption.Ascending)
                {
                    funcQ.Boost = -1;
                }
                spatialWeight = funcQ.CreateWeight(this);
                spatialWeight.GetSumOfSquaredWeights();

                luceneFilters.Add(new QueryWrapperFilter(currentWeight.Query));
            }

            spatialFilter = new ChainedFilter(luceneFilters.ToArray(), 1);
        }
        public object ComputeFieldValue(Sitecore.ContentSearch.IIndexable indexable)
        {
            var indexableItem = indexable as SitecoreIndexableItem;

            if (indexableItem == null)
            {
                return(null);
            }

            var item = (Sitecore.Data.Items.Item)indexableItem;

            if (item == null)
            {
                return(null);
            }

            var latLon = item[SourceFieldName];

            if (latLon == "" || latLon == "NULL")
            {
                return(null);
            }

            // Convert from georss point to normal X, Y format
            latLon = latLon.Replace(" ", ", ");

            var spatialContext = SpatialContext.GEO;
            var geohashTree    = new GeohashPrefixTree(spatialContext, 10);
            var strategy       = new RecursivePrefixTreeStrategy(geohashTree, FieldName);

            var          shape            = spatialContext.ReadShape(latLon);
            var          grid             = strategy.GetGrid();
            int          levelForDistance = grid.GetLevelForDistance(strategy.DistErrPct);
            IList <Node> list             = grid.GetNodes(shape, levelForDistance, true);

            return(list.Select(node => node.GetTokenString()));
        }
            public IEnumerable <Param> ParamsProvider()
            {
                var ctorArgs = new List <Param>();

                SpatialContext    ctx = SpatialContext.GEO;
                SpatialPrefixTree grid;
                SpatialStrategy   strategy;

                grid     = new QuadPrefixTree(ctx, 25);
                strategy = new RecursivePrefixTreeStrategy(grid, "recursive_quad");
                ctorArgs.Add(new Param(strategy));

                grid     = new GeohashPrefixTree(ctx, 12);
                strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash");
                ctorArgs.Add(new Param(strategy));

                strategy = new PointVectorStrategy(ctx, "pointvector");
                ctorArgs.Add(new Param(strategy));

                strategy = new BBoxStrategy(ctx, "bbox");
                ctorArgs.Add(new Param(strategy));

                return(ctorArgs);
            }
Exemple #14
0
        public void GetFieldSettings(List <FlattenedObject> props, Document doc, List <KeyValuePair <string, Analyzer> > analyzers)
        {
            foreach (var p in props)
            {
                if (p == null)
                {
                    continue;
                }
                if (analyzers != null)
                {
                    if (p.Analyzer != null)
                    {
                        analyzers.Add(new KeyValuePair <string, Analyzer>(p.Key, p.Analyzer));
                    }
                }
                if (doc != null)
                {
                    if (p.Value is int || p.Value is int?)
                    {
                        var nf = new Int32Field(p.Key, int.Parse(p.Value.ToString()), p.FieldStoreSetting);
                        doc.Add(nf);
                    }
                    else if (p.Value is long || p.Value is long?)
                    {
                        var nf = new Int64Field(p.Key, long.Parse(p.Value.ToString()), p.FieldStoreSetting);
                        doc.Add(nf);
                    }
                    else if (p.Value is float || p.Value is float?)
                    {
                        var nf = new SingleField(p.Key, float.Parse(p.Value.ToString()), p.FieldStoreSetting);
                        doc.Add(nf);
                    }
                    else if (p.Value is double || p.Value is double?)
                    {
                        var nf = new DoubleField(p.Key, double.Parse(p.Value.ToString()), p.FieldStoreSetting);
                        doc.Add(nf);
                    }
                    else if (p.Spatial)
                    {
                        if (p.Value == null || string.IsNullOrEmpty(p.Value.ToString()))
                        {
                            continue;
                        }
                        var name               = p.Key;// p.Key.IndexOf('.')>-1?p.Key.Substring(0,p.Key.LastIndexOf('.')):p.Key;
                        int maxLevels          = 11;
                        SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
                        var strat              = new RecursivePrefixTreeStrategy(grid, name);

                        //var strat = new PointVectorStrategy(ctx,name);
                        var xyArr = p.Value.ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        if (xyArr.Length != 2)
                        {
                            continue;
                        }
                        double x;
                        double y;
                        if (!double.TryParse(xyArr[0], out x) || !double.TryParse(xyArr[1], out y))
                        {
                            continue;
                        }
                        var point = ctx.MakePoint(x, y);
                        //var point = ctx.ReadShape(p.Value.ToString());
                        var fields = strat.CreateIndexableFields(point);
                        fields.ToList().ForEach(x => doc.Add(x));

                        IPoint pt = (IPoint)point;
                        //doc.Add(new StoredField(strat.FieldName, pt.X.ToString(CultureInfo.InvariantCulture) + " " + pt.Y.ToString(CultureInfo.InvariantCulture)));
                    }
                    else
                    {
                        string value = p.Value == null ? null : (p.KeepValueCasing ? p.Value.ToString() : p.Value.ToString().ToLower());
                        Field  f     = null;
                        if (p.FieldIndexSetting == Field.Index.ANALYZED || p.FieldIndexSetting == Field.Index.ANALYZED_NO_NORMS)
                        {
                            f = new TextField(p.Key, value ?? string.Empty, p.FieldStoreSetting);
                        }
                        else
                        {
                            f = new StringField(p.Key, value ?? string.Empty, p.FieldStoreSetting);
                        }
                        doc.Add(f);
                    }
                }
            }
        }
Exemple #15
0
            public RecursivePrefixTreeStrategyDistranceCustomScoreProvider(IndexReader reader, RecursivePrefixTreeStrategy strategy, PointPrefixTreeFieldCacheProvider cacheProvider, Point origin)
                : base(reader)
            {
                var ctx = strategy.GetSpatialContext();

                _originPt = origin;

                _calculator = ctx.GetDistCalc();
                _nullValue  = (ctx.IsGeo() ? 180 : float.MaxValue);
                _cache      = cacheProvider.GetCache(reader);
            }
        private Document CreateLuceneDocument(DocumentIndex documentIndex)
        {
            var doc = new Document
            {
                // Always store the content item id
                new StringField("ContentItemId", documentIndex.ContentItemId.ToString(), Field.Store.YES)
            };

            foreach (var entry in documentIndex.Entries)
            {
                var store = entry.Options.HasFlag(DocumentIndexOptions.Store)
                            ? Field.Store.YES
                            : Field.Store.NO;

                switch (entry.Type)
                {
                case DocumentIndex.Types.Boolean:
                    // Store "true"/"false" for booleans
                    doc.Add(new StringField(entry.Name, Convert.ToString(entry.Value).ToLowerInvariant(), store));
                    break;

                case DocumentIndex.Types.DateTime:
                    if (entry.Value != null)
                    {
                        if (entry.Value is DateTimeOffset)
                        {
                            doc.Add(new StringField(entry.Name, DateTools.DateToString(((DateTimeOffset)entry.Value).UtcDateTime, DateResolution.SECOND), store));
                        }
                        else
                        {
                            doc.Add(new StringField(entry.Name, DateTools.DateToString(((DateTime)entry.Value).ToUniversalTime(), DateResolution.SECOND), store));
                        }
                    }
                    else
                    {
                        doc.Add(new StringField(entry.Name, "NULL", store));
                    }
                    break;

                case DocumentIndex.Types.Integer:
                    if (entry.Value != null && Int64.TryParse(entry.Value.ToString(), out var value))
                    {
                        doc.Add(new Int64Field(entry.Name, value, store));
                    }
                    else
                    {
                        doc.Add(new StringField(entry.Name, "NULL", store));
                    }

                    break;

                case DocumentIndex.Types.Number:
                    if (entry.Value != null)
                    {
                        doc.Add(new DoubleField(entry.Name, Convert.ToDouble(entry.Value), store));
                    }
                    else
                    {
                        doc.Add(new StringField(entry.Name, "NULL", store));
                    }
                    break;

                case DocumentIndex.Types.Text:
                    if (entry.Value != null && !String.IsNullOrEmpty(Convert.ToString(entry.Value)))
                    {
                        if (entry.Options.HasFlag(DocumentIndexOptions.Analyze))
                        {
                            doc.Add(new TextField(entry.Name, Convert.ToString(entry.Value), store));
                        }
                        else
                        {
                            doc.Add(new StringField(entry.Name, Convert.ToString(entry.Value), store));
                        }
                    }
                    else
                    {
                        if (entry.Options.HasFlag(DocumentIndexOptions.Analyze))
                        {
                            doc.Add(new TextField(entry.Name, "NULL", store));
                        }
                        else
                        {
                            doc.Add(new StringField(entry.Name, "NULL", store));
                        }
                    }
                    break;

                case DocumentIndex.Types.GeoPoint:
                    var strategy = new RecursivePrefixTreeStrategy(_grid, entry.Name);
                    if (entry.Value != null && entry.Value is DocumentIndex.GeoPoint point)
                    {
                        var geoPoint = _ctx.MakePoint((double)point.Longitude, (double)point.Latitude);
                        foreach (var field in strategy.CreateIndexableFields(geoPoint))
                        {
                            doc.Add(field);
                        }

                        if (entry.Options.HasFlag(DocumentIndexOptions.Store))
                        {
                            doc.Add(new StoredField(strategy.FieldName, $"{point.Latitude},{point.Longitude}"));
                        }
                    }
                    else
                    {
                        doc.Add(new StringField(strategy.FieldName, "NULL", store));
                    }
                    break;
                }
            }

            return(doc);
        }
Exemple #17
0
        public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter)
        {
            if (type != "geo_distance")
            {
                return(null);
            }

            if (!(toFilter is BooleanQuery booleanQuery))
            {
                return(null);
            }

            var queryObj = filter as JObject;

            if (queryObj.Properties().Count() != 2)
            {
                return(null);
            }

            var ctx = SpatialContext.Geo;

            var maxLevels = 11; //results in sub-meter precision for geohash

            //  This can also be constructed from SpatialPrefixTreeFactory
            SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);

            JProperty distanceProperty = null;
            JProperty geoProperty      = null;

            foreach (var jProperty in queryObj.Properties())
            {
                if (jProperty.Name.Equals("distance", StringComparison.Ordinal))
                {
                    distanceProperty = jProperty;
                }
                else
                {
                    geoProperty = jProperty;
                }
            }

            if (distanceProperty == null || geoProperty == null)
            {
                return(null);
            }

            var strategy = new RecursivePrefixTreeStrategy(grid, geoProperty.Name);

            if (!TryParseDistance((string)distanceProperty.Value, out var distanceDegrees))
            {
                return(null);
            }

            if (!TryGetPointFromJToken(geoProperty.Value, out var point))
            {
                return(null);
            }

            var circle = ctx.MakeCircle(point.X, point.Y, distanceDegrees);

            var args = new SpatialArgs(SpatialOperation.Intersects, circle);

            var spatialQuery      = strategy.MakeQuery(args);
            var valueSource       = strategy.MakeRecipDistanceValueSource(circle);
            var valueSourceFilter = new ValueSourceFilter(new QueryWrapperFilter(spatialQuery), valueSource, 0, 1);

            booleanQuery.Add(new FunctionQuery(valueSource), Occur.MUST);

            return(new FilteredQuery(booleanQuery, valueSourceFilter));
        }
Exemple #18
0
        public static TopDocs DistanceFilter_RecursivePrefixTreeStrategy(Searcher searcher, RecursivePrefixTreeStrategy strategy, Point myLocation)
        {
            var ctx = strategy.GetSpatialContext();

            var q      = new MatchAllDocsQuery();
            var filter = strategy.MakeFilter(new SpatialArgs(SpatialOperation.Intersects,
                                                             ctx.MakeCircle(myLocation,
                                                                            DistanceUtils.Dist2Degrees(2000,
                                                                                                       DistanceUtils
                                                                                                       .EARTH_MEAN_RADIUS_KM))));

            // Reverse sorting...
            var sortField = new SortField(null, SortField.SCORE, true);

            TopDocs hits = searcher.Search(q, filter, 100, new Sort(sortField));

            return(hits);
        }
Exemple #19
0
        public bool Index(string indexName, IEnumerable <IDictionary <string, object> > items, bool archive = true)
        {
            if (!IndexExists(indexName))
            {
                throw new Exception("Index not exists");
            }

            if (items == null || items.Count() == 0)
            {
                return(true);
            }

            var mapping = _resources.GetMapping(indexName);

            List <Document> docs = new List <Document>();

            foreach (var item in items)
            {
                if (item == null)
                {
                    continue;
                }

                var itemType = item.GetType();
                var doc      = new Document();

                foreach (var field in mapping.Fields)
                {
                    #region AutoSetValues

                    switch (field.FieldType)
                    {
                    case FieldTypes.GuidType:
                        doc.Add(new StringField(
                                    field.Name,
                                    Guid.NewGuid().ToString("N").ToLower(),
                                    Field.Store.YES));
                        continue;
                    }

                    #endregion

                    if (!item.ContainsKey(field.Name))
                    {
                        continue;
                    }

                    var value = item[field.Name];
                    if (value == null)
                    {
                        continue;
                    }

                    switch (field.FieldType)
                    {
                    case FieldTypes.StringType:
                        if (field.Index)
                        {
                            doc.Add(new StringField(
                                        field.Name,
                                        value.ToString(),
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, value.ToString()));
                        }
                        break;

                    case FieldTypes.TextType:
                        if (field.Index)
                        {
                            doc.Add(new TextField(
                                        field.Name,
                                        value.ToString(),
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, value.ToString()));
                        }
                        break;

                    case FieldTypes.Int32Type:
                        if (field.Index)
                        {
                            doc.Add(new Int32Field(
                                        field.Name,
                                        value.ToInt32(),
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, Convert.ToInt32(value)));
                        }
                        break;

                    case FieldTypes.DoubleType:
                        if (field.Index)
                        {
                            doc.Add(new DoubleField(
                                        field.Name,
                                        value.ToDouble(),
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, Convert.ToDouble(value)));
                        }
                        break;

                    case FieldTypes.SingleType:
                        if (field.Index)
                        {
                            doc.Add(new SingleField(
                                        field.Name,
                                        value.ToSingle(),
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, Convert.ToSingle(value)));
                        }
                        break;

                    case FieldTypes.DateTimeType:
                        if (field.Index)
                        {
                            value = DateTools.DateToString(Convert.ToDateTime(value.ToString()).ToUniversalTime(), DateTools.Resolution.SECOND);
                            doc.Add(new StringField(
                                        field.Name,
                                        (string)value,
                                        field.Store ? Field.Store.YES : Field.Store.NO));
                        }
                        else
                        {
                            doc.Add(new Lucene.Net.Documents.StoredField(field.Name, value.ToString()));
                        }
                        break;

                    case FieldTypes.GeoType:
                        InitSpatial();

                        GeoType geoValue = GeoType.Parse(value);

                        if (geoValue is GeoPoint && geoValue.IsValid())
                        {
                            var geoPoint = (GeoPoint)geoValue;
                            var strategy = new RecursivePrefixTreeStrategy(_tree, field.Name);
                            var point    = _spatialContext.MakePoint(geoPoint.Longidute, geoPoint.Latitude);
                            foreach (var f in strategy.CreateIndexableFields(point))
                            {
                                doc.Add(f);
                            }
                            if (field.Store)
                            {
                                doc.Add(new Lucene.Net.Documents.StoredField(field.Name, geoPoint.ToString()));
                            }
                        }
                        break;
                    }
                }
                docs.Add(doc);
            }

            //lock (_writeLocker)
            {
                var writer = _resources.GetIndexWriter(indexName);
                writer.AddDocuments(docs);

                writer.Flush(triggerMerge: false, applyAllDeletes: false);
            }

            if (archive)
            {
                _archive.Index(indexName, items);
            }

            return(true);
        }