Skip to content

Commit

Permalink
Feat/resolve stats (#883)
Browse files Browse the repository at this point in the history
* add resolve aggregation function with tests

* add basic aggregation TS types

* cleanup

* improve comments

---------

Co-authored-by: Ciaran Schutte <[email protected]>
  • Loading branch information
ciaranschutte and Ciaran Schutte authored Aug 14, 2024
1 parent 9224979 commit 249608f
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 0 deletions.
49 changes: 49 additions & 0 deletions modules/server/src/network/aggregations/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
import { SupportedAggregation, SUPPORTED_AGGREGATIONS } from '../common';
import { Aggregations, NetworkAggregation, NumericAggregations } from '../types';

// TODO: implement
export const resolveAggregations = (networkResults: void) => null;

/**
* Resolve aggregation based on aggregation type
* @param type
* @param aggregations
*/
export const resolveToNetworkAggregation = <T>(
type: SupportedAggregation,
aggregations: Aggregations[],
) => {
if (type === SUPPORTED_AGGREGATIONS.Aggregations) {
resolveAggregation(aggregations);
} else if (type === SUPPORTED_AGGREGATIONS.NumericAggregations) {
resolveNumericAggregation(aggregations);
} else {
// no types match
throw Error('No matching aggregation type');
}
};

/**
* Takes an array of the same aggregation type and computes the singular type
* eg. NumericAggregation => NetworkNumericAggregation
*
* @param aggregations
* @returns
*/
export const resolveAggregation = (aggregations: Aggregations[]): NetworkAggregation => {
const emptyAggregation: NetworkAggregation = { bucket_count: 0, buckets: [] };

const resolvedAggregation = aggregations.reduce((resolvedAggregation, agg) => {
const computedBucketCount = resolvedAggregation.bucket_count + agg.bucket_count;
const computedBuckets = agg.buckets.map(({ key, doc_count }) => {
// potentially expensive "find" if array of buckets is very large
const bucket = resolvedAggregation.buckets.find((bucket) => bucket.key === key);
return { key, doc_count: (bucket?.doc_count || 0) + doc_count };
});
return { bucket_count: computedBucketCount, buckets: computedBuckets };
}, emptyAggregation);
return resolvedAggregation;
};

const resolveNumericAggregation = (aggregations: NumericAggregations) => {
// TODO: implement
throw Error('Not implemented');
};
27 changes: 27 additions & 0 deletions modules/server/src/network/aggregations/tests/aggregation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { resolveAggregation } from '..';
import { aggregation } from './fixture';

describe('Aggregation', () => {
it('should resolve multiple objects of type Aggregation into a single object of type NetworkAggregation', () => {
const result = resolveAggregation([aggregation.inputA, aggregation.inputB]);

const resultForMaleCount =
result.buckets.find((bucket) => bucket.key === 'Male')?.doc_count || 0;
const resultForFemaleCount =
result.buckets.find((bucket) => bucket.key === 'Female')?.doc_count || 0;

const expectedMaleCount =
(aggregation.inputA.buckets.find((bucket) => bucket.key === 'Male')?.doc_count || 0) +
(aggregation.inputB.buckets.find((bucket) => bucket.key === 'Male')?.doc_count || 0);

const expectedFemaleCount =
(aggregation.inputA.buckets.find((bucket) => bucket.key === 'Female')?.doc_count || 0) +
(aggregation.inputB.buckets.find((bucket) => bucket.key === 'Female')?.doc_count || 0);

expect(result.bucket_count).toEqual(
aggregation.inputA.bucket_count + aggregation.inputB.bucket_count,
);
expect(resultForMaleCount).toEqual(expectedMaleCount);
expect(resultForFemaleCount).toEqual(expectedFemaleCount);
});
});
54 changes: 54 additions & 0 deletions modules/server/src/network/aggregations/tests/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Aggregations } from '@/network/types';

// Aggregation
const inputA: Aggregations = {
bucket_count: 82,
buckets: [
{
key: 'Male',
doc_count: 70,
},
{
key: 'Female',
doc_count: 12,
},
],
};

const inputB: Aggregations = {
bucket_count: 715,
buckets: [
{
key: 'Male',
doc_count: 15,
},
{
key: 'Female',
doc_count: 700,
},
],
};

const inputC: Aggregations = {
bucket_count: 1565,
buckets: [
{
key: 'Male',
doc_count: 765,
},
{
key: 'Female',
doc_count: 800,
},
{
key: 'Unknown',
doc_count: 0,
},
],
};

export const aggregation = {
inputA,
inputB,
inputC,
};
17 changes: 17 additions & 0 deletions modules/server/src/network/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,20 @@ export type RemoteConnectionData = {
errors: string[];
status: ConnectionStatus;
};

export type Bucket = {
doc_count: number;
key: string;
};

export type Aggregations = {
bucket_count: number;
buckets: Bucket[];
};

export type NumericAggregations = {};

export type NetworkAggregation = {
bucket_count: number;
buckets: Bucket[];
};

0 comments on commit 249608f

Please sign in to comment.