Aggregate Collection


title: “Aggregate Collection”

Aggregate methods run MongoDB aggregation pipelines against a collection, returning results as either BSON documents or JSON strings.


Methods

Method Returns Description
AggregateAsync BsonDocument[] Returns BSON documents for C# processing
AggregateAsJsonAsync string Returns raw JSON string

When to Use Each

Method Use Case
AggregateAsync C# applications that process results programmatically
AggregateAsJsonAsync Web APIs that pass JSON directly to clients

Examples

AggregateAsync (BSON)

var pipeline = new BsonDocument[]
{
    new BsonDocument("$match", new BsonDocument("_t", "Person")),
    new BsonDocument("$group", new BsonDocument
    {
        ["_id"] = "$Department",
        ["count"] = new BsonDocument("$sum", 1)
    }),
    new BsonDocument("$sort", new BsonDocument("count", -1))
};

var results = await client.AggregateAsync(instance, "KeepObjects", pipeline);

foreach (var doc in results)
{
    var department = doc["_id"].AsString;
    var count = doc["count"].AsInt32;
    Console.WriteLine($"{department}: {count} people");
}

AggregateAsJsonAsync (JSON)

var pipeline = new BsonDocument[]
{
    new BsonDocument("$match", new BsonDocument("_t", "Controller")),
    new BsonDocument("$group", new BsonDocument
    {
        ["_id"] = "$Status.IsOnline",
        ["count"] = new BsonDocument("$sum", 1)
    })
};

var jsonResult = await client.AggregateAsJsonAsync(instance, "KeepObjects", pipeline);
// Returns: [{"_id": true, "count": 15}, {"_id": false, "count": 3}]

return Content(jsonResult, "application/json");

Aggregate As Json Async

Example in C#

// Returns: IEnumerable<String>
var item = await client.AggregateAsJsonAsync(FolderInfo folder, String collectionName, BsonDocument operations, Int32 queryTimeout, Boolean jsonStrict, Boolean includeGlobal, String hints);

The AggregateAsJsonAsync method executes a MongoDB aggregation pipeline and returns the results as raw JSON. This is useful when you need the raw JSON response for custom parsing, logging, or integration with other systems.

Method Signature

public async Task<string> AggregateAsJsonAsync(string instanceId, string typeName, string pipeline)

Description

The AggregateAsJsonAsync method provides direct access to MongoDB aggregation results in JSON format. Unlike AggregateAsync, which deserializes results into typed objects, this method returns raw JSON strings for:

  • Custom Parsing: Handle complex or dynamic result structures
  • Logging & Debugging: Inspect raw aggregation results
  • Integration: Pass JSON directly to other systems or APIs
  • Flexibility: Work with aggregation results that don’t map to existing types

Parameters

Parameter Type Description
instanceId string The unique identifier of the Keep instance
typeName string The collection type to aggregate (e.g., “CardholderInfo”, “EventInfo”)
pipeline string A JSON string representing the MongoDB aggregation pipeline

Return Value

Type Description
Task<string> Raw JSON string containing the aggregation results

Usage Example

using Feenics.Keep.WebApi.Wrapper;
using System.Text.Json;

var client = new Client("https://keep.feenics.com");
await client.OpenAsync("username", "password", "my-app");

// Define an aggregation pipeline
string pipeline = @"[
    { ""$match"": { ""Status"": ""Active"" } },
    { ""$group"": { 
        ""_id"": ""$Department"", 
        ""count"": { ""$sum"": 1 } 
    }},
    { ""$sort"": { ""count"": -1 } }
]";

// Execute aggregation and get raw JSON
string jsonResult = await client.AggregateAsJsonAsync(
    instanceId,
    "CardholderInfo",
    pipeline
);

// Output raw JSON
Console.WriteLine("Raw JSON Result:");
Console.WriteLine(jsonResult);

// Parse if needed
using var doc = JsonDocument.Parse(jsonResult);
foreach (var element in doc.RootElement.EnumerateArray())
{
    string dept = element.GetProperty("_id").GetString();
    int count = element.GetProperty("count").GetInt32();
    Console.WriteLine($"  {dept}: {count} cardholders");
}

Dynamic Result Processing

using Feenics.Keep.WebApi.Wrapper;
using Newtonsoft.Json.Linq;

// Complex aggregation with dynamic results
string pipeline = @"[
    { ""$match"": { ""ServerTimeStampUtc"": { ""$gte"": { ""$date"": """ + 
        DateTime.UtcNow.AddDays(-7).ToString("o") + @""" } } },
    { ""$group"": {
        ""_id"": {
            ""date"": { ""$dateToString"": { ""format"": ""%Y-%m-%d"", ""date"": ""$ServerTimeStampUtc"" } },
            ""type"": ""$EventType""
        },
        ""count"": { ""$sum"": 1 }
    }},
    { ""$sort"": { ""_id.date"": 1 } }
]";

string json = await client.AggregateAsJsonAsync(instanceId, "EventInfo", pipeline);

// Parse with Newtonsoft.Json for dynamic access
JArray results = JArray.Parse(json);
foreach (var item in results)
{
    Console.WriteLine($"Date: {item["_id"]["date"]}, Type: {item["_id"]["type"]}, Count: {item["count"]}");
}

Logging & Debugging Example

using Feenics.Keep.WebApi.Wrapper;
using Microsoft.Extensions.Logging;

public class AggregationService
{
    private readonly Client _client;
    private readonly ILogger<AggregationService> _logger;
    
    public async Task<string> RunAndLogAggregationAsync(
        string instanceId, 
        string typeName, 
        string pipeline)
    {
        _logger.LogDebug("Executing aggregation on {TypeName}", typeName);
        _logger.LogTrace("Pipeline: {Pipeline}", pipeline);
        
        try
        {
            string result = await _client.AggregateAsJsonAsync(
                instanceId, 
                typeName, 
                pipeline
            );
            
            _logger.LogDebug("Aggregation completed. Response size: {Size} bytes", 
                result.Length);
            _logger.LogTrace("Raw result: {Result}", result);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Aggregation failed for {TypeName}", typeName);
            throw;
        }
    }
}

Integration Example

using Feenics.Keep.WebApi.Wrapper;
using System.Net.Http;

public class DataExporter
{
    private readonly Client _keepClient;
    private readonly HttpClient _httpClient;
    
    public async Task ExportAggregationToExternalApiAsync(string instanceId)
    {
        string pipeline = @"[
            { ""$group"": { 
                ""_id"": ""$Department"", 
                ""employees"": { ""$push"": ""$CommonName"" }
            }}
        ]";
        
        // Get raw JSON from Keep
        string json = await _keepClient.AggregateAsJsonAsync(
            instanceId, 
            "CardholderInfo", 
            pipeline
        );
        
        // Send directly to external API
        var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
        await _httpClient.PostAsync("https://analytics.example.com/import", content);
    }
}

When to Use AggregateAsJsonAsync vs AggregateAsync

Use Case Recommended Method
Typed result objects AggregateAsync<T>
Dynamic/unknown structure AggregateAsJsonAsync
Logging raw responses AggregateAsJsonAsync
Forwarding to other APIs AggregateAsJsonAsync
Custom JSON parsing AggregateAsJsonAsync

Important Notes

💡 Raw JSON: Returns exactly what the server sends—no deserialization

💡 Performance: Slightly faster than typed aggregation (no object mapping)

⚠️ Parsing: You are responsible for parsing the JSON correctly

Aggregate Async

Example in C#

// Returns: IEnumerable<BsonDocument>
var bsonDocument = await client.AggregateAsync(FolderInfo folder, String collectionName, BsonDocument operations, Int32 queryTimeout, Boolean includeGlobal, String hints);

title: “AggregateAsync”

Run MongoDB aggregation pipelines against a collection. Returns BSON documents for complex data analysis, grouping, and transformation.


Method Signature

Task<IEnumerable<BsonDocument>> AggregateAsync(
    FolderInfo folder,
    string collection,
    BsonDocument[] pipeline,
    int queryTimeout = 600,
    bool jsonStrict = false
)

Parameters

Parameter Type Description
folder FolderInfo The folder context for the aggregation
collection string MongoDB collection name (usually KeepObjects)
pipeline BsonDocument[] Array of aggregation stages
queryTimeout int Query timeout in seconds (default: 600)
jsonStrict bool Use strict JSON mode

Examples

C# Wrapper

// Count people by department
var pipeline = new BsonDocument[]
{
    new BsonDocument("$match", new BsonDocument("_t", "Person")),
    new BsonDocument("$group", new BsonDocument
    {
        ["_id"] = "$Department",
        ["count"] = new BsonDocument("$sum", 1)
    })
};

var results = await client.AggregateAsync(instance, "KeepObjects", pipeline);

foreach (var doc in results)
{
    Console.WriteLine($"Department: {doc["_id"]}, Count: {doc["count"]}");
}
// Get controller online/offline counts
var pipeline = new BsonDocument[]
{
    new BsonDocument("$match", new BsonDocument("_t", "Controller")),
    new BsonDocument("$group", new BsonDocument
    {
        ["_id"] = "$Status.IsOnline",
        ["count"] = new BsonDocument("$sum", 1)
    })
};

var results = await client.AggregateAsync(instance, "KeepObjects", pipeline);

cURL

curl -X GET \
  "https://api.acresecurity.cloud/api/f/{instance-key}/aggregate?queryTimeout=600&jsonStrict=false" \
  -H "Authorization: Bearer TOKEN_GOES_HERE" \
  -H "Content-Type: application/json" \
  -d '[{"$match":{"_t":"Person"}},{"$group":{"_id":"$Department","count":{"$sum":1}}}]'

Common Pipeline Stages

Stage Description Example
$match Filter documents { "$match": { "_t": "Person" } }
$group Group and aggregate { "$group": { "_id": "$field", "count": { "$sum": 1 } } }
$sort Sort results { "$sort": { "count": -1 } }
$limit Limit results { "$limit": 10 }
$project Shape output { "$project": { "name": 1, "count": 1 } }