public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "simple_query_string") { return(null); } var queryString = query["query"]?.Value <string>(); var fields = query["fields"]?.Values <string>() ?? new string[0]; var defaultOperator = query["default_operator"]?.Value <string>().ToLowerInvariant() ?? "or"; var weights = fields.ToDictionary(field => field, field => 1.0f); var queryParser = new SimpleQueryParser(context.DefaultAnalyzer, weights); switch (defaultOperator) { case "and": queryParser.DefaultOperator = Occur.MUST; break; case "or": queryParser.DefaultOperator = Occur.SHOULD; break; } return(queryParser.Parse(queryString)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "term") { return(null); } var first = query.Properties().First(); // A term query has only one member, which can either be a string or an object switch (first.Value.Type) { case JTokenType.String: return(new TermQuery(new Term(first.Name, first.Value.ToString()))); case JTokenType.Object: var obj = (JObject)first.Value; var value = obj.Property("value").Value.Value <string>(); var termQuery = new TermQuery(new Term(first.Name, value)); if (obj.TryGetValue("boost", out var boost)) { termQuery.Boost = boost.Value <float>(); } return(termQuery); default: throw new ArgumentException("Invalid term query"); } }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "wildcard") { return(null); } var first = query.Properties().First(); switch (first.Value.Type) { case JTokenType.String: return(new WildcardQuery(new Term(first.Name, first.Value.ToString()))); case JTokenType.Object: var obj = (JObject)first.Value; if (!obj.TryGetValue("value", out var value)) { throw new ArgumentException("Missing value in wildcard query"); } var wildCardQuery = new WildcardQuery(new Term(value.Value <string>())); if (obj.TryGetValue("boost", out var boost)) { wildCardQuery.Boost = boost.Value <float>(); } return(wildCardQuery); default: throw new ArgumentException("Invalid wildcard query"); } }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "match") { return(null); } var first = query.Properties().First(); var boolQuery = new BooleanQuery(); switch (first.Value.Type) { case JTokenType.String: foreach (var term in LuceneQueryService.Tokenize(first.Name, first.Value.ToString(), context.DefaultAnalyzer)) { boolQuery.Add(new TermQuery(new Term(first.Name, term)), Occur.SHOULD); } return(boolQuery); case JTokenType.Object: var obj = (JObject)first.Value; var value = obj.Property("query")?.Value.Value <string>(); if (obj.TryGetValue("boost", out var boost)) { boolQuery.Boost = boost.Value <float>(); } var occur = Occur.SHOULD; if (obj.TryGetValue("operator", out var op)) { occur = op.ToString() == "and" ? Occur.MUST : Occur.SHOULD; } var terms = LuceneQueryService.Tokenize(first.Name, value, context.DefaultAnalyzer); if (!terms.Any()) { if (obj.TryGetValue("zero_terms_query", out var zeroTermsQuery)) { if (zeroTermsQuery.ToString() == "all") { return(new MatchAllDocsQuery()); } } } foreach (var term in terms) { boolQuery.Add(new TermQuery(new Term(first.Name, term)), occur); } return(boolQuery); default: throw new ArgumentException("Invalid query"); } }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "fuzzy") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var queryObj = filter as JObject; var first = queryObj.Properties().First(); FuzzyQuery fuzzyQuery; switch (first.Value.Type) { case JTokenType.String: fuzzyQuery = new FuzzyQuery(new Term(first.Name, first.Value.ToString())); break; case JTokenType.Object: var obj = (JObject)first.Value; if (!obj.TryGetValue("value", out var value)) { throw new ArgumentException("Missing value in fuzzy query"); } obj.TryGetValue("fuzziness", out var fuzziness); obj.TryGetValue("prefix_length", out var prefixLength); obj.TryGetValue("max_expansions", out var maxExpansions); fuzzyQuery = new FuzzyQuery( new Term(first.Name, value.Value <string>()), fuzziness?.Value <int>() ?? LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE, prefixLength?.Value <int>() ?? 0, maxExpansions?.Value <int>() ?? 50, true); if (obj.TryGetValue("boost", out var boost)) { fuzzyQuery.Boost = boost.Value <float>(); } break; default: throw new ArgumentException("Invalid fuzzy query"); } booleanQuery.Add(fuzzyQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(fuzzyQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "prefix") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var queryObj = filter as JObject; var first = queryObj.Properties().First(); // A prefix query has only one member, which can either be a string or an object PrefixQuery prefixQuery; switch (first.Value.Type) { case JTokenType.String: prefixQuery = new PrefixQuery(new Term(first.Name, first.Value.ToString())); break; case JTokenType.Object: var obj = (JObject)first.Value; if (obj.TryGetValue("value", out var value)) { prefixQuery = new PrefixQuery(new Term(first.Name, value.Value <string>())); } else if (obj.TryGetValue("prefix", out var prefix)) { prefixQuery = new PrefixQuery(new Term(first.Name, prefix.Value <string>())); } else { throw new ArgumentException("Prefix query misses prefix value"); } if (obj.TryGetValue("boost", out var boost)) { prefixQuery.Boost = boost.Value <float>(); } break; default: throw new ArgumentException("Invalid prefix query"); } booleanQuery.Add(prefixQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(prefixQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "match_phrase") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var queryObj = filter as JObject; var first = queryObj.Properties().First(); var phraseQuery = new PhraseQuery(); JToken value; switch (first.Value.Type) { case JTokenType.String: value = first.Value; break; case JTokenType.Object: var obj = (JObject)first.Value; if (!obj.TryGetValue("value", out value)) { throw new ArgumentException("Missing value in match phrase query"); } // TODO: read "analyzer" property if (obj.TryGetValue("slop", out var slop)) { phraseQuery.Slop = slop.Value <int>(); } break; default: throw new ArgumentException("Invalid wildcard query"); } foreach (var term in LuceneQueryService.Tokenize(first.Name, value.Value <string>(), context.DefaultAnalyzer)) { phraseQuery.Add(new Term(first.Name, term)); } booleanQuery.Add(phraseQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(phraseQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
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 Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "simple_query_string") { return(null); } var queryString = query["query"]?.Value <string>(); var fields = query["fields"]?.Value <string>() ?? ""; var defaultOperator = query["default_operator"]?.Value <string>() ?? "and"; var queryParser = new SimpleQueryParser(context.DefaultAnalyzer, ""); return(queryParser.Parse(queryString)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "query_string") { return(null); } var queryString = query["query"]?.Value <string>(); var defaultField = query["default_field"]?.Value <string>(); var queryParser = new QueryParser(context.DefaultVersion, "", context.DefaultAnalyzer); return(queryParser.Parse(queryString)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "match_all") { return(null); } var matchAllQuery = new MatchAllDocsQuery(); if (query.TryGetValue("boost", out var boost)) { matchAllQuery.Boost = boost.Value <float>(); } return(matchAllQuery); }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "terms") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var queryObj = filter as JObject; var first = queryObj.Properties().First(); var field = first.Name; var boolQuery = new BooleanQuery(); switch (first.Value.Type) { case JTokenType.Array: foreach (var item in ((JArray)first.Value)) { if (item.Type != JTokenType.String) { throw new ArgumentException($"Invalid term in terms query"); } boolQuery.Add(new TermQuery(new Term(field, item.Value <string>())), Occur.SHOULD); } break; case JTokenType.Object: throw new ArgumentException("The terms lookup query is not supported"); default: throw new ArgumentException("Invalid terms query"); } booleanQuery.Add(boolQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(boolQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "prefix") { return(null); } var first = query.Properties().First(); // A prefix query has only one member, which can either be a string or an object switch (first.Value.Type) { case JTokenType.String: return(new PrefixQuery(new Term(first.Name, first.Value.ToString()))); case JTokenType.Object: var obj = (JObject)first.Value; PrefixQuery prefixQuery = null; if (obj.TryGetValue("value", out var value)) { prefixQuery = new PrefixQuery(new Term(first.Name, value.Value <string>())); } else if (obj.TryGetValue("prefix", out var prefix)) { prefixQuery = new PrefixQuery(new Term(first.Name, prefix.Value <string>())); } else { throw new ArgumentException("Prefix query misses prefix value"); } if (obj.TryGetValue("boost", out var boost)) { prefixQuery.Boost = boost.Value <float>(); } return(prefixQuery); default: throw new ArgumentException("Invalid prefix query"); } }
private Query CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, Query query, JToken filter) { Query filteredQuery = null; var queryObj = filter as JObject; switch (filter.Type) { case JTokenType.Object: var first = queryObj.Properties().First(); foreach (var queryProvider in _filters) { filteredQuery = queryProvider.CreateFilteredQuery(builder, context, first.Name, first.Value, query); if (filteredQuery != null) { break; } } break; case JTokenType.Array: foreach (var item in ((JArray)filter)) { var firstQuery = item.First() as JProperty; foreach (var queryProvider in _filters) { filteredQuery = queryProvider.CreateFilteredQuery(builder, context, firstQuery.Name, firstQuery.Value, query); if (filteredQuery != null) { break; } } } break; default: throw new ArgumentException($"Invalid value in boolean query"); } return(filteredQuery); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "fuzzy") { return(null); } var first = query.Properties().First(); switch (first.Value.Type) { case JTokenType.String: return(new FuzzyQuery(new Term(first.Name, first.Value.ToString()))); case JTokenType.Object: var obj = (JObject)first.Value; if (!obj.TryGetValue("value", out var value)) { throw new ArgumentException("Missing value in fuzzy query"); } obj.TryGetValue("fuzziness", out var fuzziness); obj.TryGetValue("prefix_length", out var prefixLength); obj.TryGetValue("max_expansions", out var maxExpansions); var fuzzyQuery = new FuzzyQuery( new Term(first.Name, value.Value <string>()), fuzziness?.Value <int>() ?? LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE, prefixLength?.Value <int>() ?? 0, maxExpansions?.Value <int>() ?? 50, true); if (obj.TryGetValue("boost", out var boost)) { fuzzyQuery.Boost = boost.Value <float>(); } return(fuzzyQuery); default: throw new ArgumentException("Invalid fuzzy query"); } }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "match_all") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var matchAllQuery = new MatchAllDocsQuery(); booleanQuery.Add(matchAllQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(matchAllQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "simple_query_string") { return(null); } var queryString = query["query"]?.Value <string>(); var fields = query["fields"]?.Values <string>() ?? new string[0]; var defaultOperator = query["default_operator"]?.Value <string>().ToLowerInvariant() ?? "or"; var weight = 1.0f; var weights = fields.ToDictionary(field => field, field => weight); foreach (var field in fields) { var fieldWeightArray = field.Split('^', 2); if (fieldWeightArray.Length > 1 && Single.TryParse(fieldWeightArray[1], out weight)) { weights.Remove(field); weights.Add(fieldWeightArray[0], weight); } } var queryParser = new SimpleQueryParser(context.DefaultAnalyzer, weights); switch (defaultOperator) { case "and": queryParser.DefaultOperator = Occur.MUST; break; case "or": queryParser.DefaultOperator = Occur.SHOULD; break; } return(queryParser.Parse(queryString)); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "terms") { return(null); } var first = query.Properties().First(); string field = first.Name; var boolQuery = new BooleanQuery(); switch (first.Value.Type) { case JTokenType.Array: foreach (var item in ((JArray)first.Value)) { if (item.Type != JTokenType.String) { throw new ArgumentException($"Invalid term in terms query"); } boolQuery.Add(new TermQuery(new Term(field, item.Value <string>())), BooleanClause.Occur.SHOULD); } break; case JTokenType.Object: throw new ArgumentException("The terms lookup query is not supported"); default: throw new ArgumentException("Invalid terms query"); } return(boolQuery); }
public Query CreateQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JObject query) { if (type != "bool") { return(null); } var boolQuery = new BooleanQuery(); foreach (var property in query.Properties()) { var occur = BooleanClause.Occur.MUST; switch (property.Name.ToLowerInvariant()) { case "must": occur = BooleanClause.Occur.MUST; break; case "mustnot": case "must_not": occur = BooleanClause.Occur.MUST_NOT; break; case "should": occur = BooleanClause.Occur.SHOULD; break; case "boost": boolQuery.Boost = query.Value <float>(); break; case "minimum_should_match": boolQuery.MinimumNumberShouldMatch = query.Value <int>(); break; default: throw new ArgumentException($"Invalid property '{property.Name}' in boolean query"); } switch (property.Value.Type) { case JTokenType.Object: break; case JTokenType.Array: foreach (var item in ((JArray)property.Value)) { if (item.Type != JTokenType.Object) { throw new ArgumentException($"Invalid value in boolean query"); } boolQuery.Add(builder.CreateQueryFragment(context, (JObject)item), occur); } break; default: throw new ArgumentException($"Invalid value in boolean query"); } } return(boolQuery); }
public async Task <LuceneQueryResults> Query(AdminQueryViewModel model, Boolean returnContentItems) { //if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageIndexes)) //{ // return Unauthorized(); //} // model.Indices = _luceneIndexManager.List().ToArray(); model.Indices = (await _luceneIndexSettingsService.GetSettingsAsync()).Select(x => x.IndexName).ToArray(); // Can't query if there are no indices //if (model.Indices.Length == 0) //{ // return RedirectToAction("Index"); //} if (String.IsNullOrEmpty(model.IndexName)) { model.IndexName = model.Indices[0]; } //if (!_luceneIndexManager.Exists(model.IndexName)) //{ // return NotFound(); //} //if (String.IsNullOrWhiteSpace(model.DecodedQuery)) //{ // return View(model); //} if (String.IsNullOrEmpty(model.Parameters)) { model.Parameters = "{ }"; } // var luceneSettings = await _luceneIndexingService.GetLuceneSettingsAsync(); // var stopwatch = new Stopwatch(); //stopwatch.Start(); var luceneQueryResults = new LuceneQueryResults(); await _luceneIndexManager.SearchAsync(model.IndexName, async searcher => { var analyzer = _luceneAnalyzerManager.CreateAnalyzer("standardanalyzer"); var context = new LuceneQueryContext(searcher, LuceneSettings.DefaultVersion, analyzer); var templateContext = _liquidTemplateManager.Context;// new TemplateContext(); var parameters = JsonConvert.DeserializeObject <Dictionary <string, object> >(model.Parameters); foreach (var parameter in parameters) { templateContext.SetValue(parameter.Key, parameter.Value); } var tokenizedContent = await _liquidTemplateManager.RenderAsync(model.DecodedQuery, NullEncoder.Default, templateContext); try { var parameterizedQuery = JObject.Parse(tokenizedContent); var docs = await _queryService.SearchAsync(context, parameterizedQuery); // model.Documents = docs.ScoreDocs.Select(hit => searcher.Doc(hit.Doc)).ToList(); if (returnContentItems) { // Load corresponding content item versions var contentItemVersionIds = docs.TopDocs.ScoreDocs.Select(x => searcher.Doc(x.Doc).Get("Content.ContentItem.ContentItemVersionId")).ToArray(); var contentItems = await _session.Query <ContentItem, ContentItemIndex>(x => x.ContentItemVersionId.IsIn(contentItemVersionIds)).ListAsync(); // Reorder the result to preserve the one from the lucene query var indexed = contentItems.ToDictionary(x => x.ContentItemVersionId, x => x); luceneQueryResults.Items = contentItemVersionIds.Select(x => indexed[x]).ToArray(); } else { var results = new List <JObject>(); foreach (var document in docs.TopDocs.ScoreDocs.Select(hit => searcher.Doc(hit.Doc))) { results.Add(new JObject(document.Select(x => new JProperty(x.Name, x.GetStringValue())))); } luceneQueryResults.Items = results; } } catch (Exception e) { Logger.LogError(e, "Error while executing query"); // ModelState.AddModelError(nameof(model.DecodedQuery), "Invalid query"); } // stopwatch.Stop(); // model.Elapsed = stopwatch.Elapsed; }); return(luceneQueryResults); }
public async Task <IActionResult> Query(AdminQueryViewModel model, [FromServices] ITokenizer tokenizer) { if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageIndexes)) { return(Unauthorized()); } model.Indices = _luceneIndexManager.List().ToArray(); // Can't query if there are no indices if (model.Indices.Length == 0) { return(RedirectToAction("Index")); } if (String.IsNullOrEmpty(model.IndexName)) { model.IndexName = model.Indices[0]; } if (!_luceneIndexManager.Exists(model.IndexName)) { return(NotFound()); } if (String.IsNullOrWhiteSpace(model.DecodedQuery)) { return(View(model)); } if (String.IsNullOrEmpty(model.Parameters)) { model.Parameters = "{ }"; } var luceneSettings = await _luceneIndexingService.GetLuceneSettingsAsync(); var stopwatch = new Stopwatch(); stopwatch.Start(); await _luceneIndexManager.SearchAsync(model.IndexName, async searcher => { var analyzer = _luceneAnalyzerManager.CreateAnalyzer("standardanalyzer"); var context = new LuceneQueryContext(searcher, LuceneSettings.DefaultVersion, analyzer); var tokenizedContent = tokenizer.Tokenize(model.DecodedQuery, JObject.Parse(model.Parameters)); try { var parameterizedQuery = JObject.Parse(tokenizedContent); var docs = await _queryService.SearchAsync(context, parameterizedQuery); model.Documents = docs.ScoreDocs.Select(hit => searcher.Doc(hit.Doc)).ToList(); } catch (Exception e) { Logger.LogError("Error while executing query: {0}", e.Message); ModelState.AddModelError(nameof(model.DecodedQuery), "Invalid query"); } stopwatch.Stop(); model.Elapsed = stopwatch.Elapsed; }); return(View(model)); }
public async Task <IActionResult> Query(AdminQueryViewModel model) { if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageIndexes)) { return(Forbid()); } model.Indices = (await _luceneIndexSettingsService.GetSettingsAsync()).Select(x => x.IndexName).ToArray(); // Can't query if there are no indices if (model.Indices.Length == 0) { return(RedirectToAction("Index")); } if (String.IsNullOrEmpty(model.IndexName)) { model.IndexName = model.Indices[0]; } if (!_luceneIndexManager.Exists(model.IndexName)) { return(NotFound()); } if (String.IsNullOrWhiteSpace(model.DecodedQuery)) { return(View(model)); } if (String.IsNullOrEmpty(model.Parameters)) { model.Parameters = "{ }"; } var stopwatch = new Stopwatch(); stopwatch.Start(); await _luceneIndexManager.SearchAsync(model.IndexName, async searcher => { var analyzer = _luceneAnalyzerManager.CreateAnalyzer(await _luceneIndexSettingsService.GetIndexAnalyzerAsync(model.IndexName)); var context = new LuceneQueryContext(searcher, LuceneSettings.DefaultVersion, analyzer); var templateContext = _liquidTemplateManager.Context; var parameters = JsonConvert.DeserializeObject <Dictionary <string, object> >(model.Parameters); foreach (var parameter in parameters) { templateContext.SetValue(parameter.Key, parameter.Value); } var tokenizedContent = await _liquidTemplateManager.RenderAsync(model.DecodedQuery, _javaScriptEncoder); try { var parameterizedQuery = JObject.Parse(tokenizedContent); var luceneTopDocs = await _queryService.SearchAsync(context, parameterizedQuery); if (luceneTopDocs != null) { model.Documents = luceneTopDocs.TopDocs.ScoreDocs.Select(hit => searcher.Doc(hit.Doc)).ToList(); model.Count = luceneTopDocs.Count; } } catch (Exception e) { _logger.LogError(e, "Error while executing query"); ModelState.AddModelError(nameof(model.DecodedQuery), S["Invalid query : {0}", e.Message]); } stopwatch.Stop(); model.Elapsed = stopwatch.Elapsed; }); return(View(model)); }
public FilteredQuery CreateFilteredQuery(ILuceneQueryService builder, LuceneQueryContext context, string type, JToken filter, Query toFilter) { if (type != "range") { return(null); } if (!(toFilter is BooleanQuery booleanQuery)) { return(null); } var queryObj = filter as JObject; var range = queryObj.Properties().First(); Query rangeQuery; switch (range.Value.Type) { case JTokenType.Object: var field = range.Name; JToken gt = null; JToken lt = null; var tokenType = JTokenType.None; float? boost = null; bool includeLower = false, includeUpper = false; foreach (var element in ((JObject)range.Value).Properties()) { switch (element.Name.ToLowerInvariant()) { case "gt": gt = element.Value; tokenType = gt.Type; break; case "gte": gt = element.Value; tokenType = gt.Type; includeLower = true; break; case "lt": lt = element.Value; tokenType = lt.Type; break; case "lte": lt = element.Value; tokenType = lt.Type; includeUpper = true; break; case "boost": boost = element.Value.Value <float>(); break; } } if (gt != null && lt != null && gt.Type != lt.Type) { throw new ArgumentException("Lower and upper bound range types don't match"); } switch (tokenType) { case JTokenType.Integer: var minInt = gt?.Value <long>(); var maxInt = lt?.Value <long>(); rangeQuery = NumericRangeQuery.NewInt64Range(field, minInt, maxInt, includeLower, includeUpper); break; case JTokenType.Float: var minFloat = gt?.Value <double>(); var maxFloat = lt?.Value <double>(); rangeQuery = NumericRangeQuery.NewDoubleRange(field, minFloat, maxFloat, includeLower, includeUpper); break; case JTokenType.String: var minString = gt?.Value <string>(); var maxString = lt?.Value <string>(); rangeQuery = TermRangeQuery.NewStringRange(field, minString, maxString, includeLower, includeUpper); break; default: throw new ArgumentException($"Unsupported range value type: {type}"); } if (boost != null) { rangeQuery.Boost = boost.Value; } break; default: throw new ArgumentException("Invalid range query"); } booleanQuery.Add(rangeQuery, Occur.MUST); var queryFilter = new QueryWrapperFilter(rangeQuery); return(new FilteredQuery(booleanQuery, queryFilter)); }
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)); }