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));
        }
        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));
        }
Beispiel #3
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));
        }