Beispiel #1
0
        public DynamicAggregationQuery <T> AndAggregateOn(Expression <Func <T, object> > path, string displayName = null)
        {
            var propertyPath = path.ToPropertyPath('_');

            var rangeType = GetRangeType(path);

            if (rangeType != RangeType.None)
            {
                var tmp = FieldUtil.ApplyRangeSuffixIfNecessary(propertyPath, rangeType);
                _renames[propertyPath] = tmp;
                propertyPath           = tmp;
            }

            if (displayName == null)
            {
                displayName = propertyPath;
            }
            if (_facets.Count > 0)
            {
                if (_facets.Any(facet => facet.DisplayName == displayName))
                {
                    throw new InvalidOperationException("Cannot use the more than one aggregation function with the same name/without name");
                }
            }
            _facets.Add(new AggregationQuery <T> {
                Name = propertyPath, DisplayName = displayName
            });

            return(this);
        }
Beispiel #2
0
        private static void ApplyAggregation(Facet facet, FacetValue value, ArraySegment <int> docsInQuery, IndexReader indexReader, int docBase, IState state)
        {
            var name      = facet.AggregationField;
            var rangeType = FieldUtil.GetRangeTypeFromFieldName(name);

            if (rangeType == RangeType.None)
            {
                name      = FieldUtil.ApplyRangeSuffixIfNecessary(facet.AggregationField, RangeType.Double);
                rangeType = RangeType.Double;
            }

            long[]   longs   = null;
            double[] doubles = null;
            switch (rangeType)
            {
            case RangeType.Long:
                longs = FieldCache_Fields.DEFAULT.GetLongs(indexReader, name, state);
                break;

            case RangeType.Double:
                doubles = FieldCache_Fields.DEFAULT.GetDoubles(indexReader, name, state);
                break;

            default:
                throw new InvalidOperationException("Invalid range type for " + facet.Name + ", don't know how to handle " + rangeType);
            }

            for (int index = 0; index < docsInQuery.Count; index++)
            {
                var doc = docsInQuery.Array[index];

                var currentVal = rangeType == RangeType.Long ? longs[doc - docBase] : doubles[doc - docBase];
                if ((facet.Aggregation & FacetAggregation.Max) == FacetAggregation.Max)
                {
                    value.Max = Math.Max(value.Max ?? double.MinValue, currentVal);
                }

                if ((facet.Aggregation & FacetAggregation.Min) == FacetAggregation.Min)
                {
                    value.Min = Math.Min(value.Min ?? double.MaxValue, currentVal);
                }

                if ((facet.Aggregation & FacetAggregation.Sum) == FacetAggregation.Sum)
                {
                    value.Sum = currentVal + (value.Sum ?? 0d);
                }

                if ((facet.Aggregation & FacetAggregation.Average) == FacetAggregation.Average)
                {
                    value.Average = currentVal + (value.Average ?? 0d);
                }
            }
        }
Beispiel #3
0
        public static Dictionary <string, FacetResult> Parse(IReadOnlyList <Facet> facets, out Dictionary <string, Facet> defaultFacets, out Dictionary <string, List <ParsedRange> > rangeFacets)
        {
            var results = new Dictionary <string, FacetResult>();

            defaultFacets = new Dictionary <string, Facet>();
            rangeFacets   = new Dictionary <string, List <ParsedRange> >();
            foreach (var facet in facets)
            {
                var key = string.IsNullOrWhiteSpace(facet.DisplayName) ? facet.Name : facet.DisplayName;

                defaultFacets[key] = facet;
                if (facet.Aggregation != FacetAggregation.Count && facet.Aggregation != FacetAggregation.None)
                {
                    if (string.IsNullOrEmpty(facet.AggregationField))
                    {
                        throw new InvalidOperationException($"Facet {facet.Name} cannot have aggregation set to {facet.Aggregation} without having a value in AggregationField");
                    }

                    if (facet.AggregationField.EndsWith(Constants.Documents.Indexing.Fields.RangeFieldSuffix) == false)
                    {
                        var rangeType = FacetedQueryHelper.GetRangeTypeForAggregationType(facet.AggregationType);
                        facet.AggregationField = FieldUtil.ApplyRangeSuffixIfNecessary(facet.AggregationField, rangeType);
                    }
                }

                switch (facet.Mode)
                {
                case FacetMode.Default:
                    results[key] = new FacetResult();
                    break;

                case FacetMode.Ranges:
                    rangeFacets[key] = facet.Ranges
                                       .Select(range => ParseRange(facet.Name, range))
                                       .ToList();

                    results[key] = new FacetResult
                    {
                        Values = facet.Ranges
                                 .Select(range => new FacetValue {
                            Range = range
                        })
                                 .ToList()
                    };
                    break;

                default:
                    throw new ArgumentException(string.Format("Could not understand '{0}'", facet.Mode));
                }
            }

            return(results);
        }
        private static void ApplyAggregation(Dictionary <FacetAggregationField, FacetedQueryParser.FacetResult.Aggregation> aggregations, FacetValues values, ArraySegment <int> docsInQuery, IndexReader indexReader, int docBase, IState state)
        {
            foreach (var kvp in aggregations)
            {
                if (string.IsNullOrEmpty(kvp.Key.Name)) // Count
                {
                    continue;
                }

                var value = values.Get(kvp.Key);

                var name    = FieldUtil.ApplyRangeSuffixIfNecessary(kvp.Key.Name, RangeType.Double);
                var doubles = FieldCache_Fields.DEFAULT.GetDoubles(indexReader, name, state);

                var    val = kvp.Value;
                double min = value.Min ?? double.MaxValue, max = value.Max ?? double.MinValue, sum = value.Sum ?? 0, avg = value.Average ?? 0;
                int[]  array = docsInQuery.Array;
                for (var index = 0; index < docsInQuery.Count; index++)
                {
                    var doc        = array[index];
                    var currentVal = doubles[doc - docBase];
                    sum += currentVal;
                    avg += currentVal;
                    min  = Math.Min(min, currentVal);
                    max  = Math.Max(max, currentVal);
                }

                if (val.Min)
                {
                    value.Min = min;
                }

                if (val.Average)
                {
                    value.Average = avg;
                }

                if (val.Max)
                {
                    value.Max = max;
                }

                if (val.Sum)
                {
                    value.Sum = sum;
                }
            }
        }
Beispiel #5
0
        private void HandleRangeFacets(KeyValuePair <string, FacetedQueryParser.FacetResult> result, List <ReaderFacetInfo> returnedReaders, CancellationToken token)
        {
            var needToApplyAggregation = result.Value.Aggregations.Count > 0;

            foreach (var readerFacetInfo in returnedReaders)
            {
                var name          = FieldUtil.ApplyRangeSuffixIfNecessary(result.Value.AggregateBy, result.Value.RangeType);
                var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, name, _indexName, _state);

                var ranges = result.Value.Ranges;
                foreach (var kvp in termsForField)
                {
                    token.ThrowIfCancellationRequested();

                    for (int i = 0; i < ranges.Count; i++)
                    {
                        var parsedRange = ranges[i];
                        if (parsedRange.IsMatch(kvp.Key))
                        {
                            var facetValue = result.Value.Result.Values[i];

                            var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, needToApplyAggregation);
                            var intersectCount       = intersectedDocuments.Count;
                            if (intersectCount == 0)
                            {
                                continue;
                            }

                            facetValue.Count += intersectCount;

                            if (needToApplyAggregation)
                            {
                                var docsInQuery = new ArraySegment <int>(intersectedDocuments.Documents, 0, intersectedDocuments.Count);
                                ApplyAggregation(result.Value.Aggregations, facetValue, docsInQuery, readerFacetInfo.Reader, readerFacetInfo.DocBase, _state);
                                IntArraysPool.Instance.FreeArray(intersectedDocuments.Documents);
                                intersectedDocuments.Documents = null;
                            }
                        }
                    }
                }
            }
        }
Beispiel #6
0
        private static void ApplyAggregation(Dictionary <string, FacetedQueryParser.FacetResult.Aggregation> aggregations, FacetValue value, ArraySegment <int> docsInQuery, IndexReader indexReader, int docBase, IState state)
        {
            foreach (var kvp in aggregations)
            {
                if (kvp.Key == null) // Count
                {
                    continue;
                }

                var name    = FieldUtil.ApplyRangeSuffixIfNecessary(kvp.Key, RangeType.Double);
                var doubles = FieldCache_Fields.DEFAULT.GetDoubles(indexReader, name, state);

                for (var index = 0; index < docsInQuery.Count; index++)
                {
                    var doc        = docsInQuery.Array[index];
                    var currentVal = doubles[doc - docBase];

                    if (kvp.Value.Average)
                    {
                        value.Average = currentVal + (value.Average ?? 0d);
                    }

                    if (kvp.Value.Min)
                    {
                        value.Min = Math.Min(value.Min ?? double.MaxValue, currentVal);
                    }

                    if (kvp.Value.Max)
                    {
                        value.Max = Math.Max(value.Max ?? double.MinValue, currentVal);
                    }

                    if (kvp.Value.Sum)
                    {
                        value.Sum = currentVal + (value.Sum ?? 0d);
                    }
                }
            }
        }
        private void HandleRangeFacets(
            List <ReaderFacetInfo> returnedReaders,
            KeyValuePair <string, FacetedQueryParser.FacetResult> result,
            bool legacy, CancellationToken token)
        {
            var needToApplyAggregation = result.Value.Aggregations.Count > 0;
            var facetValues            = new Dictionary <string, FacetValues>();

            var ranges = result.Value.Ranges;

            foreach (var range in ranges)
            {
                var key = range.RangeText;
                if (facetValues.TryGetValue(key, out var collectionOfFacetValues))
                {
                    continue;
                }

                collectionOfFacetValues = new FacetValues(legacy);
                if (needToApplyAggregation == false)
                {
                    collectionOfFacetValues.AddDefault(key);
                }
                else
                {
                    foreach (var aggregation in result.Value.Aggregations)
                    {
                        collectionOfFacetValues.Add(aggregation.Key, key);
                    }
                }

                facetValues.Add(key, collectionOfFacetValues);
            }

            foreach (var readerFacetInfo in returnedReaders)
            {
                var name          = FieldUtil.ApplyRangeSuffixIfNecessary(result.Value.AggregateBy, result.Value.RangeType);
                var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, name, _indexName, _state);

                foreach (var kvp in termsForField)
                {
                    foreach (var range in ranges)
                    {
                        token.ThrowIfCancellationRequested();

                        if (range.IsMatch(kvp.Key) == false)
                        {
                            continue;
                        }

                        var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, needToApplyAggregation);
                        var intersectCount       = intersectedDocuments.Count;
                        if (intersectCount == 0)
                        {
                            continue;
                        }

                        var collectionOfFacetValues = facetValues[range.RangeText];
                        collectionOfFacetValues.IncrementCount(intersectCount);

                        if (needToApplyAggregation)
                        {
                            var docsInQuery = new ArraySegment <int>(intersectedDocuments.Documents, 0, intersectedDocuments.Count);
                            ApplyAggregation(result.Value.Aggregations, collectionOfFacetValues, docsInQuery, readerFacetInfo.Reader, readerFacetInfo.DocBase, _state);
                            IntArraysPool.Instance.FreeArray(intersectedDocuments.Documents);
                            intersectedDocuments.Documents = null;
                        }
                    }
                }
            }

            foreach (var kvp in facetValues)
            {
                if (kvp.Value.Any == false)
                {
                    continue;
                }

                result.Value.Result.Values.AddRange(kvp.Value.GetAll());
            }
        }