Exemplo n.º 1
0
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var ids = ctx.Source.GetIds();

            if (ids.Count > 0)
            {
                ctx.Filter &= new IdsQuery {
                    Values = ids.Select(id => new Nest.Id(id))
                }
            }
            ;

            var excludesIds = ctx.Source.GetExcludedIds();

            if (excludesIds.Count > 0)
            {
                ctx.Filter &= !new IdsQuery {
                    Values = excludesIds.Select(id => new Nest.Id(id))
                }
            }
            ;

            return(Task.CompletedTask);
        }
    }
}
Exemplo n.º 2
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var childQuery = ctx.GetSourceAs <IChildQuery>();

            if (childQuery?.ChildQuery == null)
            {
                return;
            }

            if (String.IsNullOrEmpty(childQuery.ChildQuery.Type))
            {
                throw new ArgumentException("Must specify a child type for child queries.");
            }

            // this should pass an options object that is for the child index type
            var childContext = new QueryBuilderContext <T>(childQuery.ChildQuery, ctx.Options, null, ctx, ContextType.Child);
            await _queryBuilder.BuildAsync(childContext).AnyContext();

            if ((childContext.Query == null || childContext.Query.IsConditionless) &&
                (childContext.Filter == null || childContext.Filter.IsConditionless))
            {
                return;
            }

            ctx.Filter &= new HasChildFilter {
                Query  = childContext.Query,
                Filter = childContext.Filter,
                Type   = childQuery.ChildQuery.Type
            };
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var dateRanges = ctx.Source.GetDateRanges();

            if (dateRanges.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            var elasticQueryOptions = ctx.Options.GetElasticTypeSettings();

            foreach (var dateRange in dateRanges.Where(dr => dr.UseDateRange))
            {
                string fieldName = dateRange.Field?.Name;
                if (elasticQueryOptions?.IndexType != null && !String.IsNullOrEmpty(fieldName))
                {
                    fieldName = elasticQueryOptions.IndexType.GetFieldName(fieldName);
                }

                ctx.Filter &= new DateRangeQuery {
                    Field = fieldName ?? dateRange.Field,
                    GreaterThanOrEqualTo = dateRange.GetStartDate(),
                    LessThanOrEqualTo    = dateRange.GetEndDate()
                };
            }

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var dateRanges = ctx.Source.GetDateRanges();

            if (dateRanges.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            var resolver = ctx.GetMappingResolver();

            foreach (var dateRange in dateRanges.Where(dr => dr.UseDateRange))
            {
                var rangeQuery = new DateRangeQuery {
                    Field = resolver.ResolveFieldName(dateRange.Field)
                };
                if (dateRange.UseStartDate)
                {
                    rangeQuery.GreaterThanOrEqualTo = dateRange.GetStartDate();
                }
                if (dateRange.UseEndDate)
                {
                    rangeQuery.LessThanOrEqualTo = dateRange.GetEndDate();
                }
                if (!String.IsNullOrEmpty(dateRange.TimeZone))
                {
                    rangeQuery.TimeZone = dateRange.TimeZone;
                }

                ctx.Filter &= rangeQuery;
            }

            return(Task.CompletedTask);
        }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var childQuery = ctx.Source.GetChildQuery();

            if (childQuery == null)
            {
                return;
            }

            var childContext = new QueryBuilderContext <T>(childQuery.Query, ctx.Options, null, ctx, ContextType.Child);
            await _queryBuilder.BuildAsync(childContext).AnyContext();

            if ((childContext.Query == null || ((IQueryContainer)childContext.Query).IsConditionless) &&
                (childContext.Filter == null || ((IQueryContainer)childContext.Filter).IsConditionless))
            {
                return;
            }

            ctx.Filter &= new HasChildQuery {
                Type  = childQuery.Type,
                Query = new BoolQuery {
                    Must   = new QueryContainer[] { childContext.Query },
                    Filter = new QueryContainer[] { childContext.Filter },
                }
            };
        }
Exemplo n.º 6
0
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            int limit = ctx.Options.GetLimit();

            if (limit >= ctx.Options.GetMaxLimit() || ctx.Options.ShouldUseSnapshotPaging())
            {
                ctx.Search.Size(limit);
            }
            else
            {
                // add 1 to limit if not snapshot paging so we can know if we have more results
                ctx.Search.Size(limit + 1);
            }

            // can only use search_after or skip
            if (ctx.Options.HasSearchAfter())
            {
                ctx.Search.SearchAfter(ctx.Options.GetSearchAfter());
            }
            else if (ctx.Options.HasSearchBefore())
            {
                ctx.Search.SearchAfter(ctx.Options.GetSearchBefore());
            }
            else if (ctx.Options.ShouldUseSkip())
            {
                ctx.Search.Skip(ctx.Options.GetSkip());
            }

            return(Task.CompletedTask);
        }
 public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
 {
     foreach (var builder in _partBuilders)
     {
         await builder.BuildAsync(ctx).AnyContext();
     }
 }
Exemplo n.º 8
0
        public static async Task <QueryContainer> BuildQueryAsync <T>(this IElasticQueryBuilder builder, IRepositoryQuery query, ICommandOptions options, SearchDescriptor <T> search) where T : class, new()
        {
            var ctx = new QueryBuilderContext <T>(query, options, search);
            await builder.BuildAsync(ctx).AnyContext();

            return(new BoolQuery {
                Must = new[] { ctx.Query },
                Filter = new[] { ctx.Filter ?? new MatchAllQuery() }
            });
        }
        public static async Task <QueryContainer> BuildQueryAsync <T>(this IElasticQueryBuilder builder, IRepositoryQuery query, IQueryOptions options, SearchDescriptor <T> search) where T : class, new()
        {
            var ctx = new QueryBuilderContext <T>(query, options, search);
            await builder.BuildAsync(ctx).AnyContext();

            return(new FilteredQuery {
                Filter = ctx.Filter,
                Query = ctx.Query
            });
        }
Exemplo n.º 10
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var  parentQuery = ctx.GetSourceAs <IParentQuery>();
            bool hasIds      = ctx.GetSourceAs <IIdentityQuery>()?.Ids.Count > 0;

            if (parentQuery == null)
            {
                return;
            }

            var           options       = ctx.GetOptionsAs <IElasticQueryOptions>();
            IQueryOptions parentOptions = null;

            if (options != null && options.HasParent == false)
            {
                return;
            }

            if (options != null && options.ParentSupportsSoftDeletes && hasIds == false)
            {
                if (parentQuery.ParentQuery == null)
                {
                    parentQuery.ParentQuery = new ParentQuery();
                }

                var parentType = options.ChildType.GetParentIndexType();
                if (parentType == null)
                {
                    throw new ApplicationException("ParentIndexTypeName on child index type must match the name of the parent type.");
                }

                parentOptions = new ElasticQueryOptions(parentType);
            }

            if (parentQuery.ParentQuery == null)
            {
                return;
            }

            var parentContext = new QueryBuilderContext <object>(parentQuery.ParentQuery, parentOptions, null, ctx, ContextType.Parent);
            await _queryBuilder.BuildAsync(parentContext).AnyContext();

            if ((parentContext.Query == null || parentContext.Query.IsConditionless) &&
                (parentContext.Filter == null || parentContext.Filter.IsConditionless))
            {
                return;
            }

            ctx.Filter &= new HasParentFilter {
                Query  = parentContext.Query,
                Filter = parentContext.Filter,
                Type   = options?.ChildType?.GetParentIndexType().Name
            };
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            // dont add filter to child query system filters
            if (ctx.Type == ContextType.Child)
            {
                return(Task.CompletedTask);
            }

            // get soft delete mode, use parent query as default if it exists
            var mode = ctx.Source.GetSoftDeleteMode(ctx.Parent?.Source?.GetSoftDeleteMode() ?? SoftDeleteQueryMode.ActiveOnly);

            // no filter needed if we want all
            if (mode == SoftDeleteQueryMode.All)
            {
                return(Task.CompletedTask);
            }

            // check to see if the model supports soft deletes
            var options = ctx.Options.GetElasticTypeSettings();

            if (options == null || !options.SupportsSoftDeletes)
            {
                return(Task.CompletedTask);
            }

            // if we are querying for specific ids then we don't need a deleted filter
            var ids = ctx.Source.GetIds();

            if (ids.Count > 0)
            {
                return(Task.CompletedTask);
            }

            string fieldName = options.IndexType?.GetFieldName(IsDeleted) ?? IsDeleted;

            if (mode == SoftDeleteQueryMode.ActiveOnly)
            {
                ctx.Filter &= new TermQuery {
                    Field = fieldName, Value = false
                }
            }
            ;
            else if (mode == SoftDeleteQueryMode.DeletedOnly)
            {
                ctx.Filter &= new TermQuery {
                    Field = fieldName, Value = true
                }
            }
            ;

            return(Task.CompletedTask);
        }
    }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            if (_queryBuilders == null)
            {
                Interlocked.CompareExchange(ref _queryBuilders, _registrations.OrderBy(v => v.Priority).Select(r => r.Builder).ToArray(), null);
            }

            foreach (var builder in _queryBuilders)
            {
                await builder.BuildAsync(ctx).AnyContext();
            }
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var elasticQuery = ctx.GetSourceAs <IElasticFilterQuery>();

            if (elasticQuery?.ElasticFilter == null)
            {
                return(Task.CompletedTask);
            }

            ctx.Filter &= elasticQuery.ElasticFilter;

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var searchQuery = ctx.GetSourceAs <ISearchQuery>();

            if (searchQuery == null)
            {
                return(Task.CompletedTask);
            }

            if (!String.IsNullOrEmpty(searchQuery.Filter))
            {
                var result = _parser.Parse(searchQuery.Filter);
                searchQuery.Filter = GenerateQueryVisitor.Run(AliasedQueryVisitor.Run(result, _aliasMap, ctx), ctx);

                ctx.Filter &= new QueryFilter {
                    Query = new QueryStringQuery {
                        Query           = searchQuery.Filter,
                        DefaultOperator = Operator.And,
                        AnalyzeWildcard = false
                    }.ToContainer()
                };
            }

            if (!String.IsNullOrEmpty(searchQuery.Criteria))
            {
                var result = _parser.Parse(searchQuery.Criteria);
                searchQuery.Criteria = GenerateQueryVisitor.Run(AliasedQueryVisitor.Run(result, _aliasMap, ctx), ctx);

                ctx.Query &= new QueryStringQuery {
                    Query           = searchQuery.Criteria,
                    DefaultOperator = searchQuery.DefaultCriteriaOperator == SearchOperator.Or ? Operator.Or : Operator.And,
                    AnalyzeWildcard = true
                };
            }

            if (!String.IsNullOrEmpty(searchQuery.Sort))
            {
                var result = _parser.Parse(searchQuery.Sort);
                var opt    = ctx.GetOptionsAs <IElasticQueryOptions>();
                TermToFieldVisitor.Run(result, ctx);
                AliasedQueryVisitor.Run(result, _aliasMap, ctx);
                var fields = GetReferencedFieldsQueryVisitor.Run(result);
                // TODO: Check referenced fields against opt.AllowedSortFields

                var sort = GetSortFieldsVisitor.Run(result, ctx);
                ctx.Search.Sort(sort);
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 15
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var options = ctx.Options.GetElasticTypeSettings();

            if (options.HasParent == false)
            {
                return;
            }

            var  parentQuery = ctx.Source.GetParentQuery();
            bool hasIds      = ctx.Source.GetIds().Count > 0;

            // even if no parent query has been set, run it through to get soft delete filter
            if (options.ParentSupportsSoftDeletes && hasIds == false && parentQuery == null)
            {
                parentQuery = new RepositoryQuery();
            }

            if (parentQuery == null)
            {
                return;
            }

            var parentType = options.ChildType.GetParentIndexType();

            if (parentType == null)
            {
                throw new ApplicationException("ParentIndexTypeName on child index type must match the name of the parent type.");
            }

            var parentOptions = new CommandOptions().ElasticType(parentType);

            var parentContext = new QueryBuilderContext <object>(parentQuery, parentOptions, null, ctx, ContextType.Parent);
            await _queryBuilder.BuildAsync(parentContext).AnyContext();

            if ((parentContext.Query == null || ((IQueryContainer)parentContext.Query).IsConditionless) &&
                (parentContext.Filter == null || ((IQueryContainer)parentContext.Filter).IsConditionless))
            {
                return;
            }

            ctx.Filter &= new HasParentQuery {
                Type  = parentType.Name,
                Query = new BoolQuery {
                    Must   = new QueryContainer[] { parentContext.Query },
                    Filter = new QueryContainer[] { parentContext.Filter },
                }
            };
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            // add 1 to limit if not snapshot paging so we can know if we have more results
            if (ctx.Options.HasPageLimit())
            {
                ctx.Search.Size(ctx.Options.GetLimit() + (ctx.Options.ShouldUseSnapshotPaging() == false ? 1 : 0));
            }

            if (ctx.Options.ShouldUseSkip())
            {
                ctx.Search.Skip(ctx.Options.GetSkip());
            }

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var elasticFilters = ctx.Source.GetElasticFilters();

            if (elasticFilters.Count == 0)
            {
                return(Task.CompletedTask);
            }

            foreach (var filter in elasticFilters)
            {
                ctx.Filter &= filter;
            }

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var sortFields = ctx.Source.GetSorts();

            if (sortFields.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            //var opt = ctx.GetOptionsAs<IElasticQueryOptions>();
            //foreach (var sort in sortableQuery.SortFields.Where(s => CanSortByField(opt?.AllowedSortFields, s.Field)))
            //    ctx.Search.Sort(s => s.Field(sort.Field, sort.Order == Foundatio.Repositories.Models.SortOrder.Ascending ? SortOrder.Ascending : SortOrder.Descending));
            ctx.Search.Sort(sortFields);

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var sortFields = ctx.Source.GetSorts();

            if (sortFields.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            var resolver = ctx.GetMappingResolver();

            sortFields = resolver.GetResolvedFields(sortFields);

            ctx.Search.Sort(sortFields);
            return(Task.CompletedTask);
        }
Exemplo n.º 20
0
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            string filter = ctx.Source.GetFilterExpression();
            string search = ctx.Source.GetSearchExpression();
            string sort   = ctx.Source.GetSortExpression();

            if (!String.IsNullOrEmpty(filter))
            {
                var result = _parser.Parse(filter);
                filter = GenerateQueryVisitor.Run(FieldResolverQueryVisitor.Run(result, _aliasMap, ctx), ctx);

                ctx.Filter &= new QueryStringQuery {
                    Query           = filter,
                    DefaultOperator = Operator.And,
                    AnalyzeWildcard = false
                };
            }

            if (!String.IsNullOrEmpty(search))
            {
                var result = _parser.Parse(search);
                search = GenerateQueryVisitor.Run(FieldResolverQueryVisitor.Run(result, _aliasMap, ctx), ctx);

                ctx.Query &= new QueryStringQuery {
                    Query           = search,
                    DefaultOperator = ctx.Source.GetSearchExpressionDefaultOperator() == SearchOperator.Or ? Operator.Or : Operator.And,
                    AnalyzeWildcard = true
                };
            }

            if (!String.IsNullOrEmpty(sort))
            {
                var result = _parser.Parse(sort);
                TermToFieldVisitor.Run(result, ctx);
                FieldResolverQueryVisitor.Run(result, _aliasMap, ctx);
                var fields = GetReferencedFieldsQueryVisitor.Run(result);
                // TODO: Check referenced fields against opt.AllowedSortFields

                var sortFields = GetSortFieldsVisitor.Run(result, ctx).ToList();

                ctx.Search.Sort(sortFields);
            }

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var includes = ctx.Source.GetIncludes();

            if (includes.Count > 0)
            {
                ctx.Search.Source(s => s.Includes(i => i.Fields(includes.ToArray())));
            }

            var excludes = ctx.Source.GetExcludes();

            if (excludes.Count > 0)
            {
                ctx.Search.Source(s => s.Excludes(i => i.Fields(excludes.ToArray())));
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 22
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var childQueries = ctx.Source.GetChildQueries();

            if (childQueries.Count == 0)
            {
                return;
            }

            var index = ctx.Options.GetElasticIndex();

            foreach (var childQuery in childQueries)
            {
                var childOptions = ctx.Options.Clone();
                childOptions.DocumentType(childQuery.GetDocumentType());
                var childContext = new QueryBuilderContext <object>(childQuery, childOptions, null);

                await index.QueryBuilder.BuildAsync(childContext);

                if (childContext.Filter != null && ((IQueryContainer)childContext.Filter).IsConditionless == false)
                {
                    ctx.Filter &= new HasChildQuery {
                        Type  = childQuery.GetDocumentType(),
                        Query = new BoolQuery {
                            Filter = new[] { childContext.Filter }
                        }
                    }
                }
                ;

                if (childContext.Query != null && ((IQueryContainer)childContext.Query).IsConditionless == false)
                {
                    ctx.Query &= new HasChildQuery {
                        Type  = childQuery.GetDocumentType(),
                        Query = new BoolQuery {
                            Must = new[] { childContext.Query }
                        }
                    }
                }
                ;
            }
        }
    }
}
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var fieldValuesQuery = ctx.GetSourceAs <IFieldConditionsQuery>();

            if (fieldValuesQuery?.FieldConditions == null || fieldValuesQuery.FieldConditions.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            foreach (var fieldValue in fieldValuesQuery.FieldConditions)
            {
                switch (fieldValue.Operator)
                {
                case ComparisonOperator.Equals:
                    ctx.Filter &= new TermFilter {
                        Field = fieldValue.Field, Value = fieldValue.Value
                    };
                    break;

                case ComparisonOperator.NotEquals:
                    ctx.Filter &= new NotFilter {
                        Filter = FilterContainer.From(new TermFilter {
                            Field = fieldValue.Field, Value = fieldValue.Value
                        })
                    };
                    break;

                case ComparisonOperator.IsEmpty:
                    ctx.Filter &= new MissingFilter {
                        Field = fieldValue.Field
                    };
                    break;

                case ComparisonOperator.HasValue:
                    ctx.Filter &= new ExistsFilter {
                        Field = fieldValue.Field
                    };
                    break;
                }
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 24
0
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var selectedFieldsQuery = ctx.GetSourceAs <ISelectedFieldsQuery>();

            if (selectedFieldsQuery?.SelectedFields?.Count > 0)
            {
                ctx.Search.Source(s => s.Include(selectedFieldsQuery.SelectedFields.ToArray()));
                return(Task.CompletedTask);
            }

            var opt = ctx.GetOptionsAs <IElasticQueryOptions>();

            if (opt?.DefaultExcludes?.Count > 0)
            {
                ctx.Search.Source(s => s.Exclude(opt.DefaultExcludes.ToArray()));
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 25
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var aggregationQuery = ctx.GetSourceAs <IAggregationQuery>();

            if (String.IsNullOrEmpty(aggregationQuery?.Aggregations))
            {
                return;
            }

            var opt = ctx.GetOptionsAs <IElasticQueryOptions>();

            if (opt?.AllowedAggregationFields?.Count > 0 && !(await GetAggregationFieldsAsync(aggregationQuery.Aggregations).AnyContext()).All(f => opt.AllowedAggregationFields.Contains(f)))
            {
                throw new InvalidOperationException("All aggregation fields must be allowed.");
            }

            var result = await _parser.BuildAggregationsAsync(aggregationQuery.Aggregations, ctx).AnyContext();

            ctx.Search.Aggregations(result);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var sortableQuery = ctx.GetSourceAs <ISortableQuery>();

            if (sortableQuery?.SortFields == null || sortableQuery.SortFields.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            var opt = ctx.GetOptionsAs <IElasticQueryOptions>();

            // TODO: Check SortFields against opt.AllowedSortFields
            //foreach (var sort in sortableQuery.SortFields.Where(s => CanSortByField(opt?.AllowedSortFields, s.Field.ToString())))
            //    ctx.Search.Sort(s => s.OnField(sort.Field)
            //        .Order(sort.Order == Foundatio.Repositories.Models.SortOrder.Ascending ? SortOrder.Ascending : SortOrder.Descending));

            ctx.Search.Sort(sortableQuery.SortFields);

            return(Task.CompletedTask);
        }
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var dateRangeQuery = ctx.GetSourceAs <IDateRangeQuery>();

            if (dateRangeQuery?.DateRanges == null || dateRangeQuery.DateRanges.Count <= 0)
            {
                return(Task.CompletedTask);
            }

            foreach (var dateRange in dateRangeQuery.DateRanges.Where(dr => dr.UseDateRange))
            {
                ctx.Filter &= new RangeFilter {
                    Field = dateRange.Field,
                    GreaterThanOrEqualTo = dateRange.GetStartDate().ToString("o"),
                    LowerThanOrEqualTo   = dateRange.GetEndDate().ToString("O")
                };
            }

            return(Task.CompletedTask);
        }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var elasticOptions = ctx.Options.GetElasticTypeSettings();

            if (elasticOptions?.IndexType?.QueryParser == null)
            {
                return;
            }

            string aggregations = ctx.Source.GetAggregationsExpression();

            if (String.IsNullOrEmpty(aggregations))
            {
                return;
            }

            var result = await elasticOptions.IndexType.QueryParser.BuildAggregationsAsync(aggregations, ctx).AnyContext();

            ctx.Search.Aggregations(result);
        }
Exemplo n.º 29
0
        public Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            var pagableQuery = ctx.GetSourceAs <IPagableQuery>();

            if (pagableQuery == null)
            {
                return(Task.CompletedTask);
            }

            // add 1 to limit if not auto paging so we can know if we have more results
            if (pagableQuery.ShouldUseLimit())
            {
                ctx.Search.Size(pagableQuery.GetLimit() + (pagableQuery.ShouldUseSnapshotPaging() == false ? 1 : 0));
            }

            if (pagableQuery.ShouldUseSkip())
            {
                ctx.Search.Skip(pagableQuery.GetSkip());
            }

            return(Task.CompletedTask);
        }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            string filter = ctx.Source.GetFilterExpression();
            string search = ctx.Source.GetSearchExpression();
            string sort   = ctx.Source.GetSortExpression();

            // NOTE: Calling UseScoring here to keep the query from being wrapped in a filter which happens ElasticQueryBuilderExtensions.BuildQuery
            if (!String.IsNullOrEmpty(filter))
            {
                ctx.Filter &= await _parser.BuildQueryAsync(filter, ctx.SetDefaultOperator(Operator.And).UseScoring()).AnyContext();
            }

            if (!String.IsNullOrEmpty(search))
            {
                ctx.Query &= await _parser.BuildQueryAsync(search, ctx.SetDefaultOperator(Operator.Or).UseScoring()).AnyContext();
            }

            if (!String.IsNullOrEmpty(sort))
            {
                ctx.Search.Sort(await _parser.BuildSortAsync(sort, ctx).AnyContext());
            }
        }