Пример #1
0
        /// <summary>
        /// Gets the aggregate value, by grouping, of the values in the given entity field.
        /// </summary>
        /// <returns>The sum of the values of the given property name for the entities in the <see cref="DataStore{T}"/>.</returns>
        /// <param name="groupField">Property name of field to be used in grouping.</param>
        /// <param name="aggregateField">Property name of field to be used in aggregation.  This is not necessary when using the <see cref="KinveyXamarin.EnumReduceFunction.REDUCE_FUNCTION_COUNT"/> method.</param>
        /// <param name="query">[optional] Query used to filter results prior to aggregation.</param>
        /// <param name="cacheDelegate">Delegate used to return the sum aggregate value based on what is available in offline cache.</param>
        /// <param name="ct">[optional] CancellationToken used to cancel the request.</param>
        public async Task <List <GroupAggregationResults> > GroupAndAggregateAsync(EnumReduceFunction reduceFunction, string groupField = "", string aggregateField = "", IQueryable <object> query = null, KinveyDelegate <List <GroupAggregationResults> > cacheDelegate = null, CancellationToken ct = default(CancellationToken))
        {
            FindAggregateRequest <T> findByAggregateQueryRequest = new FindAggregateRequest <T>(client, collectionName, reduceFunction, cache, storeType.ReadPolicy, DeltaSetFetchingEnabled, cacheDelegate, query, groupField, aggregateField);

            ct.ThrowIfCancellationRequested();
            return(await findByAggregateQueryRequest.ExecuteAsync());
        }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:KinveyXamarin.FindAggregateRequest`1"/> class.
 /// </summary>
 /// <param name="client">Client.</param>
 /// <param name="collection">Collection.</param>
 /// <param name="reduceFunction">Reduce function.</param>
 /// <param name="cache">Cache.</param>
 /// <param name="policy"> The <see cref="ReadPolicy"/> to be used for this request.</param>
 /// <param name="deltaSetFetchingEnabled">If set to <c>true</c> delta set fetching enabled.</param>
 /// <param name="cacheDelegate">Cache delegate.</param>
 /// <param name="query">[optional] Query used to filter the results that are to be aggregated.</param>
 /// <param name="groupField">Property name to be used for grouping.</param>
 /// <param name="aggregateField">Property name to be used for aggregation.</param>
 public FindAggregateRequest(AbstractClient client,
                             string collection,
                             EnumReduceFunction reduceFunction,
                             ICache <T> cache,
                             ReadPolicy policy,
                             bool deltaSetFetchingEnabled,
                             KinveyDelegate <List <GroupAggregationResults> > cacheDelegate,
                             IQueryable <object> query,
                             string groupField,
                             string aggregateField)
     : base(client, collection, cache, query, policy, deltaSetFetchingEnabled)
 {
     this.cacheDelegate  = cacheDelegate;
     this.reduceFunction = reduceFunction;
     this.groupField     = groupField;
     this.aggregateField = aggregateField;
 }
Пример #3
0
        public NetworkRequest <T> BuildGetAggregateRequest <T>(string collectionName, EnumReduceFunction reduceFunction, string query, string groupField, string aggregateField)
        {
            string REST_PATH = "appdata/{appKey}/{collectionName}/_group";

            var urlParameters = new Dictionary <string, string>();

            urlParameters.Add("appKey", ((KinveyClientRequestInitializer)client.RequestInitializer).AppKey);
            urlParameters.Add("collectionName", collectionName);

            JObject keyval = new JObject();

            if (!String.IsNullOrEmpty(groupField))
            {
                keyval.Add(groupField, true);
            }

            JObject initialval = new JObject();

            JObject httpBodyContent = new JObject();

            httpBodyContent.Add("key", keyval);

            string reduce = String.Empty;

            switch (reduceFunction)
            {
            case EnumReduceFunction.REDUCE_FUNCTION_SUM:
                initialval.Add("result", 0);
                reduce = $"function(doc,out){{ out.result += doc.{aggregateField}; }}";
                break;

            case EnumReduceFunction.REDUCE_FUNCTION_MIN:
                initialval.Add("result", Int32.MaxValue);
                reduce = $"function(doc,out){{ out.result = Math.min(out.result, doc.{aggregateField}); }}";
                break;

            case EnumReduceFunction.REDUCE_FUNCTION_MAX:
                initialval.Add("result", Int32.MinValue);
                reduce = $"function(doc,out){{ out.result = Math.max(out.result, doc.{aggregateField}); }}";
                break;

            case EnumReduceFunction.REDUCE_FUNCTION_AVERAGE:
                initialval.Add("result", 0);
                initialval.Add("count", 0);
                reduce = $"function(doc,out){{ out.result = (((out.result * out.count) + doc.{aggregateField}) / (out.count += 1)); }}";
                break;

            default:
                // TODO throw new KinveyException()
                break;
            }

            httpBodyContent.Add("initial", initialval);
            httpBodyContent.Add("reduce", reduce);

            if (!String.IsNullOrEmpty(query))
            {
                const char CHAR_CURLY_BRACE_OPENING = '{';
                const char CHAR_CURLY_BRACE_CLOSING = '}';
                const char CHAR_COLON = ':';
                const char CHAR_DOUBLE_QUOTATION_MARK = '"';

                JObject condition = new JObject();
                query = query.TrimStart(CHAR_CURLY_BRACE_OPENING).TrimEnd(CHAR_CURLY_BRACE_CLOSING);
                string[] cond = query.Split(CHAR_COLON);
                cond[0] = cond[0].TrimStart(CHAR_DOUBLE_QUOTATION_MARK).TrimEnd(CHAR_DOUBLE_QUOTATION_MARK);
                cond[1] = cond[1].TrimStart(CHAR_DOUBLE_QUOTATION_MARK).TrimEnd(CHAR_DOUBLE_QUOTATION_MARK);
                condition.Add(cond[0], cond[1]);

                httpBodyContent.Add("condition", condition);
            }

            NetworkRequest <T> findAggregateQuery = new NetworkRequest <T>(client, "POST", REST_PATH, httpBodyContent, urlParameters);

            client.InitializeRequest(findAggregateQuery);

            return(findAggregateQuery);
        }
Пример #4
0
        public List <GroupAggregationResults> GetAggregateResult(EnumReduceFunction reduceFunction, string groupField, string aggregateField, Expression query)
        {
            List <GroupAggregationResults> localAggregateResults = new List <GroupAggregationResults>();
            List <object> listValues = new List <object>();

            PropertyInfo propInfo = typeof(T).GetRuntimeProperty(aggregateField);

            if (propInfo != null &&
                IsTypeNumber(propInfo.PropertyType))
            {
                int              skipNumber = 0;
                int              takeNumber = 0;
                bool             sort       = false;
                LambdaExpression exprSort   = null;

                var lambdaExpr = ConvertQueryExpressionToFunction(query, ref skipNumber, ref takeNumber, ref sort, ref exprSort);

                if (String.IsNullOrEmpty(groupField))
                {
                    // Not grouping results be a specified field, so just aggregate over all entities
                    // that pass through the query filter, if provided.
                    GroupAggregationResults gar = new GroupAggregationResults();
                    gar.GroupField = null;

                    // TODO do "skip" and "take" have to be taken into account in group aggregate functions?
                    if (lambdaExpr != null)
                    {
                        listValues = (from t in dbConnectionSync.Table <T>().Where(lambdaExpr) select t.GetType().GetRuntimeProperty(aggregateField).GetValue(t, null)).ToList();
                    }
                    else
                    {
                        listValues = (from t in dbConnectionSync.Table <T>() select t.GetType().GetRuntimeProperty(aggregateField).GetValue(t, null)).ToList();
                    }

                    switch (reduceFunction)
                    {
                    case EnumReduceFunction.REDUCE_FUNCTION_SUM:
                        foreach (int val in listValues)
                        {
                            gar.Result += val;
                        }
                        break;

                    case EnumReduceFunction.REDUCE_FUNCTION_MIN:
                        gar.Result = int.MaxValue;
                        foreach (int val in listValues)
                        {
                            gar.Result = Math.Min(gar.Result, val);
                        }
                        break;

                    case EnumReduceFunction.REDUCE_FUNCTION_MAX:
                        gar.Result = int.MinValue;
                        foreach (int val in listValues)
                        {
                            gar.Result = Math.Max(gar.Result, val);
                        }
                        break;

                    case EnumReduceFunction.REDUCE_FUNCTION_AVERAGE:
                        int count = 0;
                        int total = 0;
                        foreach (int val in listValues)
                        {
                            total += val;
                            count++;
                        }
                        gar.Result = total / count;
                        break;

                    default:
                        // TODO throw new KinveyException
                        break;
                    }

                    localAggregateResults.Add(gar);
                }
                else
                {
                    // A grouping field was supplied, so aggregate
                    // result per group created on the group field
                    IEnumerable <IGrouping <object, T> > grouplist;
                    if (lambdaExpr != null)
                    {
                        grouplist = from t in dbConnectionSync.Table <T>().Where(lambdaExpr)
                                    group t by t.GetType().GetRuntimeProperty(groupField).GetValue(t, null);
                    }
                    else
                    {
                        grouplist = from t in dbConnectionSync.Table <T>()
                                    group t by t.GetType().GetRuntimeProperty(groupField).GetValue(t, null);
                    }

                    foreach (var grouping in grouplist)
                    {
                        int result = 0;
                        listValues = (from x in grouping select x.GetType().GetRuntimeProperty(aggregateField).GetValue(x, null)).ToList();

                        GroupAggregationResults gar = new GroupAggregationResults();
                        gar.GroupField = grouping.Key.ToString();

                        switch (reduceFunction)
                        {
                        case EnumReduceFunction.REDUCE_FUNCTION_SUM:
                            foreach (int val in listValues)
                            {
                                result += val;
                            }
                            break;

                        case EnumReduceFunction.REDUCE_FUNCTION_MIN:
                            result = int.MaxValue;
                            foreach (int val in listValues)
                            {
                                result = Math.Min(result, val);
                            }
                            break;

                        case EnumReduceFunction.REDUCE_FUNCTION_MAX:
                            result = int.MinValue;
                            foreach (int val in listValues)
                            {
                                result = Math.Max(result, val);
                            }
                            break;

                        case EnumReduceFunction.REDUCE_FUNCTION_AVERAGE:
                            int count = 0;
                            int total = 0;
                            foreach (int val in listValues)
                            {
                                total += val;
                                count++;
                            }
                            result = total / count;
                            break;

                        default:
                            // TODO throw new KinveyException
                            break;
                        }

                        gar.Result = result;
                        localAggregateResults.Add(gar);
                    }
                }
            }

            return(localAggregateResults);
        }