private void HandleFacets( List <ReaderFacetInfo> returnedReaders, KeyValuePair <string, FacetedQueryParser.FacetResult> result, Dictionary <string, Dictionary <string, FacetValues> > facetsByName, bool legacy, CancellationToken token) { var needToApplyAggregation = result.Value.Aggregations.Count > 0; foreach (var readerFacetInfo in returnedReaders) { var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, result.Value.AggregateBy, _indexName, _state); if (facetsByName.TryGetValue(result.Key, out var facetValues) == false) { facetsByName[result.Key] = facetValues = new Dictionary <string, FacetValues>(); } foreach (var kvp in termsForField) { token.ThrowIfCancellationRequested(); var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, needToApplyAggregation); var intersectCount = intersectedDocuments.Count; if (intersectCount == 0) { continue; } if (facetValues.TryGetValue(kvp.Key, out var collectionOfFacetValues) == false) { var range = FacetedQueryHelper.GetRangeName(result.Value.AggregateBy, kvp.Key); collectionOfFacetValues = new FacetValues(legacy); if (needToApplyAggregation == false) { collectionOfFacetValues.AddDefault(range); } else { foreach (var aggregation in result.Value.Aggregations) { collectionOfFacetValues.Add(aggregation.Key, range); } } facetValues.Add(kvp.Key, collectionOfFacetValues); } 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); } } } }
private void Validate(IEnumerable <Facet> facets) { foreach (var facet in facets) { if (FacetedQueryHelper.IsAggregationNumerical(facet.Aggregation) && FacetedQueryHelper.IsAggregationTypeNumerical(facet.AggregationType) && FacetedQueryHelper.GetSortOptionsForFacet(facet.AggregationField, _fields) == SortOptions.None) { throw new InvalidOperationException(string.Format("Index '{0}' does not have sorting enabled for a numerical field '{1}'.", _indexName, facet.AggregationField)); } } }
private void HandleFacets(List <ReaderFacetInfo> returnedReaders, KeyValuePair <string, FacetedQueryParser.FacetResult> result, Dictionary <string, Dictionary <string, FacetValue> > facetsByName) { foreach (var readerFacetInfo in returnedReaders) { var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, result.Value.AggregateBy, _indexName, _state); if (facetsByName.TryGetValue(result.Key, out Dictionary <string, FacetValue> facetValues) == false) { facetsByName[result.Key] = facetValues = new Dictionary <string, FacetValue>(); } foreach (var kvp in termsForField) { var needToApplyAggregation = result.Value.Aggregations.Count > 0; var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, needToApplyAggregation); var intersectCount = intersectedDocuments.Count; if (intersectCount == 0) { continue; } if (facetValues.TryGetValue(kvp.Key, out FacetValue facetValue) == false) { facetValue = new FacetValue { Range = FacetedQueryHelper.GetRangeName(result.Value.AggregateBy, kvp.Key) }; facetValues.Add(kvp.Key, facetValue); } 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); } } } }
public Dictionary <string, FacetResult> FacetedQuery(FacetQueryServerSide query, JsonOperationContext context, Func <string, SpatialField> getSpatialField, CancellationToken token) { var results = FacetedQueryParser.Parse(query.Facets, out Dictionary <string, Facet> defaultFacets, out Dictionary <string, List <FacetedQueryParser.ParsedRange> > rangeFacets); var facetsByName = new Dictionary <string, Dictionary <string, FacetValue> >(); uint fieldsHash = 0; if (query.Metadata.IsDistinct) { fieldsHash = CalculateQueryFieldsHash(query); } var baseQuery = GetLuceneQuery(context, query.Metadata, query.QueryParameters, _analyzer, getSpatialField); var returnedReaders = GetQueryMatchingDocuments(_searcher, baseQuery, _state); foreach (var facet in defaultFacets.Values) { if (facet.Mode != FacetMode.Default) { continue; } Dictionary <string, HashSet <IndexSearcherHolder.StringCollectionValue> > distinctItems = null; HashSet <IndexSearcherHolder.StringCollectionValue> alreadySeen = null; if (query.Metadata.IsDistinct) { distinctItems = new Dictionary <string, HashSet <IndexSearcherHolder.StringCollectionValue> >(); } foreach (var readerFacetInfo in returnedReaders) { var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, facet.Name, _indexName, _state); if (facetsByName.TryGetValue(facet.DisplayName, out Dictionary <string, FacetValue> facetValues) == false) { facetsByName[facet.DisplayName] = facetValues = new Dictionary <string, FacetValue>(); } foreach (var kvp in termsForField) { if (query.Metadata.IsDistinct) { if (distinctItems.TryGetValue(kvp.Key, out alreadySeen) == false) { alreadySeen = new HashSet <IndexSearcherHolder.StringCollectionValue>(); distinctItems[kvp.Key] = alreadySeen; } } var needToApplyAggregation = (facet.Aggregation == FacetAggregation.None || facet.Aggregation == FacetAggregation.Count) == false; var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, alreadySeen, query, fieldsHash, needToApplyAggregation, context); var intersectCount = intersectedDocuments.Count; if (intersectCount == 0) { continue; } if (facetValues.TryGetValue(kvp.Key, out FacetValue facetValue) == false) { facetValue = new FacetValue { Range = FacetedQueryHelper.GetRangeName(facet.Name, kvp.Key) }; facetValues.Add(kvp.Key, facetValue); } facetValue.Hits += intersectCount; facetValue.Count = facetValue.Hits; if (needToApplyAggregation) { var docsInQuery = new ArraySegment <int>(intersectedDocuments.Documents, 0, intersectedDocuments.Count); ApplyAggregation(facet, facetValue, docsInQuery, readerFacetInfo.Reader, readerFacetInfo.DocBase, _state); } } } } foreach (var range in rangeFacets) { var facet = defaultFacets[range.Key]; var needToApplyAggregation = (facet.Aggregation == FacetAggregation.None || facet.Aggregation == FacetAggregation.Count) == false; Dictionary <string, HashSet <IndexSearcherHolder.StringCollectionValue> > distinctItems = null; HashSet <IndexSearcherHolder.StringCollectionValue> alreadySeen = null; if (query.Metadata.IsDistinct) { distinctItems = new Dictionary <string, HashSet <IndexSearcherHolder.StringCollectionValue> >(); } foreach (var readerFacetInfo in returnedReaders) { var termsForField = IndexedTerms.GetTermsAndDocumentsFor(readerFacetInfo.Reader, readerFacetInfo.DocBase, facet.Name, _indexName, _state); if (query.Metadata.IsDistinct) { if (distinctItems.TryGetValue(range.Key, out alreadySeen) == false) { alreadySeen = new HashSet <IndexSearcherHolder.StringCollectionValue>(); distinctItems[range.Key] = alreadySeen; } } var facetResult = results[range.Key]; var ranges = range.Value; foreach (var kvp in termsForField) { for (int i = 0; i < ranges.Count; i++) { var parsedRange = ranges[i]; if (parsedRange.IsMatch(kvp.Key)) { var facetValue = facetResult.Values[i]; var intersectedDocuments = GetIntersectedDocuments(new ArraySegment <int>(kvp.Value), readerFacetInfo.Results, alreadySeen, query, fieldsHash, needToApplyAggregation, context); var intersectCount = intersectedDocuments.Count; if (intersectCount == 0) { continue; } facetValue.Hits += intersectCount; facetValue.Count = facetValue.Hits; if (needToApplyAggregation) { var docsInQuery = new ArraySegment <int>(intersectedDocuments.Documents, 0, intersectedDocuments.Count); ApplyAggregation(facet, facetValue, docsInQuery, readerFacetInfo.Reader, readerFacetInfo.DocBase, _state); IntArraysPool.Instance.FreeArray(intersectedDocuments.Documents); intersectedDocuments.Documents = null; } } } } } } UpdateFacetResults(results, query, defaultFacets, facetsByName); CompleteFacetCalculationsStage(results, defaultFacets); foreach (var readerFacetInfo in returnedReaders) { IntArraysPool.Instance.FreeArray(readerFacetInfo.Results.Array); } return(results); }
private void ApplyAggregation(Facet facet, FacetValue value, ArraySegment <int> docsInQuery, IndexReader indexReader, int docBase) { var sortOptionsForFacet = FacetedQueryHelper.GetSortOptionsForFacet(facet.AggregationField, _fields); switch (sortOptionsForFacet) { case SortOptions.String: case SortOptions.StringVal: //case SortOptions.Custom: // TODO arek case SortOptions.None: throw new InvalidOperationException(string.Format("Cannot perform numeric aggregation on index field '{0}'. You must set the Sort mode of the field to Int, Float, Long or Double.", FacetedQueryHelper.TryTrimRangeSuffix(facet.AggregationField))); case SortOptions.NumericLong: var longs = FieldCache_Fields.DEFAULT.GetLongs(indexReader, facet.AggregationField); for (int index = 0; index < docsInQuery.Count; index++) { var doc = docsInQuery.Array[index]; var currentVal = longs[doc - docBase]; if (facet.Aggregation.HasFlag(FacetAggregation.Max)) { value.Max = Math.Max(value.Max ?? double.MinValue, currentVal); } if (facet.Aggregation.HasFlag(FacetAggregation.Min)) { value.Min = Math.Min(value.Min ?? double.MaxValue, currentVal); } if (facet.Aggregation.HasFlag(FacetAggregation.Sum)) { value.Sum = currentVal + (value.Sum ?? 0d); } if (facet.Aggregation.HasFlag(FacetAggregation.Average)) { value.Average = currentVal + (value.Average ?? 0d); } } break; case SortOptions.NumericDouble: var doubles = FieldCache_Fields.DEFAULT.GetDoubles(indexReader, facet.AggregationField); for (int index = 0; index < docsInQuery.Count; index++) { var doc = docsInQuery.Array[index]; var currentVal = doubles[doc - docBase]; if (facet.Aggregation.HasFlag(FacetAggregation.Max)) { value.Max = Math.Max(value.Max ?? double.MinValue, currentVal); } if (facet.Aggregation.HasFlag(FacetAggregation.Min)) { value.Min = Math.Min(value.Min ?? double.MaxValue, currentVal); } if (facet.Aggregation.HasFlag(FacetAggregation.Sum)) { value.Sum = currentVal + (value.Sum ?? 0d); } if (facet.Aggregation.HasFlag(FacetAggregation.Average)) { value.Average = currentVal + (value.Average ?? 0d); } } break; default: throw new ArgumentOutOfRangeException($"Not supported sort option for aggregation: {sortOptionsForFacet}"); } }