//@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); }
public RecursivePrefixTreeStrategyDistanceCustomScoreQuery(Query subQuery, RecursivePrefixTreeStrategy strategy, Point origin, String shapeField) : base(subQuery) { _strategy = strategy; _origin = origin; _cacheProvider = new PointPrefixTreeFieldCacheProvider(_strategy.GetGrid(), shapeField, 255); }
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)); }
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); }
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)); }
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); }
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); } } } }
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); }
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)); }
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); }
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); }