Beispiel #1
0
        public override int HandleMap(LazyStringValue key, IEnumerable mapResults, IndexWriteOperation writer, TransactionOperationContext indexContext, IndexingStatsScope stats)
        {
            EnsureValidStats(stats);

            var mappedResult = new DynamicJsonValue();

            using (_stats.BlittableJsonAggregation.Start())
            {
                var document = ((Document[])mapResults)[0];
                Debug.Assert(key == document.LowerId);

                foreach (var field in Definition.MapFields.Values)
                {
                    var autoIndexField = field.As <AutoIndexField>();

                    switch (autoIndexField.Aggregation)
                    {
                    case AggregationOperation.Count:
                        mappedResult[autoIndexField.Name] = 1;
                        break;

                    case AggregationOperation.Sum:
                        object fieldValue;
                        BlittableJsonTraverser.Default.TryRead(document.Data, autoIndexField.Name, out fieldValue, out _);

                        var arrayResult = fieldValue as IEnumerable <object>;

                        if (arrayResult == null)
                        {
                            // explicitly adding this even if the value isn't there, as a null
                            mappedResult[autoIndexField.Name] = fieldValue;
                            continue;
                        }

                        decimal total = 0;

                        foreach (var item in arrayResult)
                        {
                            if (item == null)
                            {
                                continue;
                            }

                            switch (BlittableNumber.Parse(item, out double doubleValue, out long longValue))
                            {
                            case NumberParseResult.Double:
                                total += (decimal)doubleValue;
                                break;

                            case NumberParseResult.Long:
                                total += longValue;
                                break;
                            }
                        }

                        mappedResult[autoIndexField.Name] = total;

                        break;
        private IEnumerable<AbstractField> GetOrCreateNumericField(IndexField field, object value, Field.Store storage, Field.TermVector termVector = Field.TermVector.NO)
        {
            var fieldNameDouble = field.Name + Constants.Documents.Indexing.Fields.RangeFieldSuffixDouble;
            var fieldNameLong = field.Name + Constants.Documents.Indexing.Fields.RangeFieldSuffixLong;

            var numericFieldDouble = GetNumericFieldFromCache(fieldNameDouble, null, storage, termVector);
            var numericFieldLong = GetNumericFieldFromCache(fieldNameLong, null, storage, termVector);

            switch (BlittableNumber.Parse(value, out double doubleValue, out long longValue))
            {
        private IEnumerable <AbstractField> GetOrCreateNumericField(IndexField field, object value, Field.Store storage, Field.TermVector termVector = Field.TermVector.NO)
        {
            var fieldName = field.Name + Constants.Indexing.Fields.RangeFieldSuffix;

            var cacheKey = new FieldCacheKey(field.Name, null, storage, termVector,
                                             _multipleItemsSameFieldCount.ToArray());

            NumericField numericField;
            CachedFieldItem <NumericField> cached;

            if (_numericFieldsCache.TryGetValue(cacheKey, out cached) == false)
            {
                _numericFieldsCache[cacheKey] = cached = new CachedFieldItem <NumericField>
                {
                    Field = numericField = new NumericField(CreateFieldName(fieldName), storage, true)
                };
            }
            else
            {
                numericField = cached.Field;
            }

            double doubleValue;
            long   longValue;

            switch (BlittableNumber.Parse(value, out doubleValue, out longValue))
            {
            case NumberParseResult.Double:
                if (field.SortOption == SortOptions.NumericLong)
                {
                    yield return(numericField.SetLongValue((long)doubleValue));
                }
                else
                {
                    yield return(numericField.SetDoubleValue(doubleValue));
                }
                break;

            case NumberParseResult.Long:
                if (field.SortOption == SortOptions.NumericDouble)
                {
                    yield return(numericField.SetDoubleValue(longValue));
                }
                else
                {
                    yield return(numericField.SetLongValue(longValue));
                }
                break;
            }
        }
Beispiel #4
0
        protected override AggregationResult AggregateOn(List <BlittableJsonReaderObject> aggregationBatch, TransactionOperationContext indexContext, CancellationToken token)
        {
            var aggregatedResultsByReduceKey = new Dictionary <BlittableJsonReaderObject, Dictionary <string, PropertyResult> >(ReduceKeyComparer.Instance);

            foreach (var obj in aggregationBatch)
            {
                token.ThrowIfCancellationRequested();

                using (obj)
                {
                    var aggregatedResult = new Dictionary <string, PropertyResult>();

                    foreach (var propertyName in obj.GetPropertyNames())
                    {
                        if (_indexDefinition.TryGetField(propertyName, out var indexField))
                        {
                            switch (indexField.Aggregation)
                            {
                            case AggregationOperation.None:
                                if (obj.TryGet(propertyName, out object groupByValue) == false)
                                {
                                    throw new InvalidOperationException($"Could not read group by value of '{propertyName}' property");
                                }

                                aggregatedResult[propertyName] = new PropertyResult
                                {
                                    ResultValue = groupByValue
                                };
                                break;

                            case AggregationOperation.Count:
                            case AggregationOperation.Sum:

                                object value;
                                if (obj.TryGetMember(propertyName, out value) == false)
                                {
                                    throw new InvalidOperationException($"Could not read numeric value of '{propertyName}' property");
                                }

                                double doubleValue;
                                long   longValue;

                                var numberType = BlittableNumber.Parse(value, out doubleValue, out longValue);
                                var aggregate  = new PropertyResult(numberType);

                                switch (numberType)
                                {
                                case NumberParseResult.Double:
                                    aggregate.ResultValue = aggregate.DoubleValue = doubleValue;
                                    break;

                                case NumberParseResult.Long:
                                    aggregate.ResultValue = aggregate.LongValue = longValue;
                                    break;

                                default:
                                    throw new ArgumentOutOfRangeException($"Unknown number type: {numberType}");
                                }

                                aggregatedResult[propertyName] = aggregate;
                                break;

                            //case FieldMapReduceOperation.None:
                            default:
                                throw new ArgumentOutOfRangeException($"Unhandled field type '{indexField.Aggregation}' to aggregate on");
                            }
                        }

                        if (_indexDefinition.GroupByFields.ContainsKey(propertyName) == false)
                        {
                            // we want to reuse existing entry to get a reduce key

                            if (obj.Modifications == null)
                            {
                                obj.Modifications = new DynamicJsonValue(obj);
                            }

                            obj.Modifications.Remove(propertyName);
                        }
                    }

                    var reduceKey = indexContext.ReadObject(obj, "reduce key");

                    if (aggregatedResultsByReduceKey.TryGetValue(reduceKey, out Dictionary <string, PropertyResult> existingAggregate) == false)
                    {
                        aggregatedResultsByReduceKey.Add(reduceKey, aggregatedResult);
                    }
                    else
                    {
                        reduceKey.Dispose();

                        foreach (var propertyResult in existingAggregate)
                        {
                            propertyResult.Value.Aggregate(aggregatedResult[propertyResult.Key]);
                        }
                    }
                }
            }

            var resultObjects = new List <Document>(aggregatedResultsByReduceKey.Count);

            foreach (var aggregationResult in aggregatedResultsByReduceKey)
            {
                aggregationResult.Key.Dispose();

                var djv = new DynamicJsonValue();

                foreach (var aggregate in aggregationResult.Value)
                {
                    djv[aggregate.Key] = aggregate.Value.ResultValue;
                }

                resultObjects.Add(new Document {
                    Data = indexContext.ReadObject(djv, "map/reduce")
                });
            }

            return(new AggregatedDocuments(resultObjects));
        }
Beispiel #5
0
        public override int HandleMap(LazyStringValue key, IEnumerable mapResults, IndexWriteOperation writer, TransactionOperationContext indexContext, IndexingStatsScope stats)
        {
            EnsureValidStats(stats);

            var mappedResult = new DynamicJsonValue();

            using (_stats.BlittableJsonAggregation.Start())
            {
                var document = ((Document[])mapResults)[0];
                Debug.Assert(key == document.LoweredKey);

                foreach (var indexField in Definition.MapFields.Values)
                {
                    switch (indexField.MapReduceOperation)
                    {
                    case FieldMapReduceOperation.Count:
                        mappedResult[indexField.Name] = 1;
                        break;

                    case FieldMapReduceOperation.Sum:
                        object        fieldValue;
                        StringSegment leftPath;
                        BlittableJsonTraverser.Default.TryRead(document.Data, indexField.Name, out fieldValue, out leftPath);

                        var arrayResult = fieldValue as IEnumerable <object>;

                        if (arrayResult == null)
                        {
                            // explicitly adding this even if the value isn't there, as a null
                            mappedResult[indexField.Name] = fieldValue;
                            continue;
                        }

                        decimal total = 0;

                        foreach (var item in arrayResult)
                        {
                            if (item == null)
                            {
                                continue;
                            }

                            double doubleValue;
                            long   longValue;

                            switch (BlittableNumber.Parse(item, out doubleValue, out longValue))
                            {
                            case NumberParseResult.Double:
                                total += (decimal)doubleValue;
                                break;

                            case NumberParseResult.Long:
                                total += longValue;
                                break;
                            }
                        }

                        mappedResult[indexField.Name] = total;

                        break;

                    case FieldMapReduceOperation.None:
                        object result;
                        BlittableJsonTraverser.Default.TryRead(document.Data, indexField.Name, out result, out leftPath);

                        // explicitly adding this even if the value isn't there, as a null
                        mappedResult[indexField.Name] = result;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                _reduceKeyProcessor.Reset();

                foreach (var groupByFieldName in Definition.GroupByFields.Keys)
                {
                    object        result;
                    StringSegment leftPath;
                    BlittableJsonTraverser.Default.TryRead(document.Data, groupByFieldName, out result, out leftPath);
                    // explicitly adding this even if the value isn't there, as a null
                    mappedResult[groupByFieldName] = result;

                    _reduceKeyProcessor.Process(indexContext.Allocator, result);
                }
            }

            BlittableJsonReaderObject mr;

            using (_stats.CreateBlittableJson.Start())
                mr = indexContext.ReadObject(mappedResult, key);

            var mapResult = _singleOutputList[0];

            mapResult.Data          = mr;
            mapResult.ReduceKeyHash = _reduceKeyProcessor.Hash;

            var resultsCount = PutMapResults(key, _singleOutputList, indexContext, stats);

            DocumentDatabase.Metrics.MapReduceMappedPerSecond.Mark(resultsCount);

            return(resultsCount);
        }