public async Task CanProcessQueryAsync(string query, string expected, bool isValid, bool usesPremiumFeatures)
        {
            var context = new ElasticQueryVisitorContext();

            IQueryNode result;

            try {
                result = await _parser.ParseAsync(query, QueryType.Query, context).AnyContext();
            } catch (Exception ex) {
                _logger.Error(ex, $"Error parsing query: {query}. Message: {ex.Message}");
                if (isValid)
                {
                    throw;
                }

                return;
            }

            // NOTE: we have to do this because we don't have access to the right query parser instance.
            result = await EventFieldsQueryVisitor.RunAsync(result, context);

            Assert.Equal(expected, await GenerateQueryVisitor.RunAsync(result, context));

            var info = await _validator.ValidateQueryAsync(result);

            _logger.Info(() => $"UsesPremiumFeatures: {info.UsesPremiumFeatures} IsValid: {info.IsValid} Message: {info.Message}");
            Assert.Equal(isValid, info.IsValid);
            Assert.Equal(usesPremiumFeatures, info.UsesPremiumFeatures);
        }
        public async Task VerifyStackFilter(string filter, int expected, int?expectedInverted = null)
        {
            Log.SetLogLevel <StackRepository>(LogLevel.Trace);

            long totalStacks = await _stackRepository.CountAsync(o => o.IncludeSoftDeletes());

            var ctx         = new ElasticQueryVisitorContext();
            var stackFilter = await new EventStackFilter().GetStackFilterAsync(filter, ctx);

            _logger.LogInformation("Finding Filter: {Filter}", stackFilter.Filter);
            var stacks = await _stackRepository.FindAsync(q => q.FilterExpression(stackFilter.Filter), o => o.SoftDeleteMode(SoftDeleteQueryMode.All).PageLimit(1000));

            Assert.Equal(expected, stacks.Total);

            _logger.LogInformation("Finding Inverted Filter: {Filter}", stackFilter.InvertedFilter);
            var invertedStacks = await _stackRepository.FindAsync(q => q.FilterExpression(stackFilter.InvertedFilter), o => o.SoftDeleteMode(SoftDeleteQueryMode.All).PageLimit(1000));

            long expectedInvert = expectedInverted ?? totalStacks - expected;

            Assert.Equal(expectedInvert, invertedStacks.Total);

            var stackIds         = new HashSet <string>(stacks.Hits.Select(h => h.Id));
            var invertedStackIds = new HashSet <string>(invertedStacks.Hits.Select(h => h.Id));

            Assert.Empty(stackIds.Intersect(invertedStackIds));
        }
        private async Task GetAggregationQueryInfoAsync(IQueryParser parser, string query, bool isValid, int maxNodeDepth, HashSet <string> fields, Dictionary <string, ICollection <string> > operations)
        {
            IQueryNode queryNode;
            var        context = new ElasticQueryVisitorContext {
                QueryType = QueryType.Aggregation
            };

            try {
                queryNode = await parser.ParseAsync(query, context);
            } catch (Exception ex) {
                _logger.LogError(ex, "Error parsing query: {Message}", ex.Message);
                if (isValid)
                {
                    throw;
                }

                return;
            }

            var info = await ValidationVisitor.RunAsync(queryNode, context);

            Assert.Equal(QueryType.Aggregation, info.QueryType);
            Assert.Equal(isValid, info.IsValid);
            Assert.Equal(maxNodeDepth, info.MaxNodeDepth);
            Assert.Equal(fields, info.ReferencedFields);
            Assert.Equal(operations, info.Operations.ToDictionary(pair => pair.Key, pair => pair.Value));
        }
        public static QueryProcessResult Validate(string query)
        {
            if (String.IsNullOrEmpty(query))
            {
                return new QueryProcessResult {
                           IsValid = true
                }
            }
            ;

            GroupNode result;

            try {
                var parser = new LuceneQueryParser();

                result = parser.Parse(query);
            } catch (Exception ex) {
                return(new QueryProcessResult {
                    Message = ex.Message
                });
            }

            var validator = new QueryProcessorVisitor(_freeFields);
            var context   = new ElasticQueryVisitorContext();

            result.Accept(validator, context);

            return(new QueryProcessResult {
                IsValid = true,
                UsesPremiumFeatures = validator.UsesPremiumFeatures
            });
        }
    }
        public static QueryProcessResult Process(string query)
        {
            if (String.IsNullOrWhiteSpace(query))
            {
                return new QueryProcessResult {
                           IsValid = true
                }
            }
            ;

            GroupNode result;

            try {
                var parser = new LuceneQueryParser();

                result = parser.Parse(query);
            } catch (Exception ex) {
                return(new QueryProcessResult {
                    Message = ex.Message
                });
            }

            var validator = new QueryProcessorVisitor(_freeFields);
            var context   = new ElasticQueryVisitorContext();

            result.Accept(validator, context);

            var expandedQuery = validator.UsesDataFields ? GenerateQueryVisitor.Run(result) : query;

            return(new QueryProcessResult {
                IsValid = true,
                UsesPremiumFeatures = validator.UsesPremiumFeatures,
                ExpandedQuery = expandedQuery
            });
        }
        public Task <IEnumerable <IFieldSort> > BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null)
        {
            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            return(GetSortFieldsVisitor.RunAsync(sort, context));
        }
        public async Task <QueryContainer> BuildQueryAsync(string query, IElasticQueryVisitorContext context = null)
        {
            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            var result = await ParseAsync(query, QueryType.Query, context).ConfigureAwait(false);

            return(await BuildQueryAsync(result, context).ConfigureAwait(false));
        }
        public async Task <IEnumerable <IFieldSort> > BuildSortAsync(string sort, IElasticQueryVisitorContext context = null)
        {
            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            var result = await ParseAsync(sort, QueryType.Sort, context).ConfigureAwait(false);

            return(await BuildSortAsync(result, context).ConfigureAwait(false));
        }
        public async Task <AggregationContainer> BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null)
        {
            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            var result = await ParseAsync(aggregations, QueryType.Aggregation, context).ConfigureAwait(false);

            return(await BuildAggregationsAsync(result, context).ConfigureAwait(false));
        }
        public void CanUseElasticQueryParserWithVisitor()
        {
            var testQueryVisitor = new TestQueryVisitor();
            var sut     = new ElasticQueryParser(c => c.AddQueryVisitor(testQueryVisitor));
            var context = new ElasticQueryVisitorContext();

            var result = sut.Parse("NOT (dog parrot)", context) as GroupNode;

            Assert.Equal(2, testQueryVisitor.GroupNodeCount);

            Assert.IsType <GroupNode>(result.Left);
            Assert.True((result.Left as GroupNode).HasParens);
            Assert.True((result.Left as GroupNode).IsNegated);
        }
        public Task <QueryContainer> BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null)
        {
            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            var q = query.GetQuery() ?? new MatchAllQuery();

            if (context?.UseScoring == false)
            {
                q = new BoolQuery {
                    Filter = new QueryContainer[] { q }
                };
            }

            return(Task.FromResult <QueryContainer>(q));
        }
        public override async Task <IQueryNode> ParseAsync(string query, string queryType = QueryType.Query, IQueryVisitorContext context = null)
        {
            if (String.IsNullOrEmpty(query))
            {
                throw new ArgumentNullException(nameof(query));
            }

            if (context == null)
            {
                context = new ElasticQueryVisitorContext();
            }

            var result = await base.ParseAsync(query, queryType, context).ConfigureAwait(false);

            SetupQueryVisitorContextDefaults(context);
            switch (queryType)
            {
            case QueryType.Aggregation:
                context.SetGetPropertyMappingFunc(_config.GetMappingProperty);
                result = await _config.AggregationVisitor.AcceptAsync(result, context).ConfigureAwait(false);

                break;

            case QueryType.Query:
                context.SetGetPropertyMappingFunc(_config.GetMappingProperty).SetDefaultFields(_config.DefaultFields);
                if (_config.DefaultIncludeResolver != null && context.GetIncludeResolver() == null)
                {
                    context.SetIncludeResolver(_config.DefaultIncludeResolver);
                }

                result = await _config.QueryVisitor.AcceptAsync(result, context).ConfigureAwait(false);

                break;

            case QueryType.Sort:
                context.SetGetPropertyMappingFunc(_config.GetMappingProperty);
                result = await _config.SortVisitor.AcceptAsync(result, context).ConfigureAwait(false);

                break;
            }

            return(result);
        }