From e99bb300fad9a0882db8cf3225037255e074b18e Mon Sep 17 00:00:00 2001 From: Leonardo <leomilho@gmail.com> Date: Tue, 28 Jan 2025 11:33:28 +0100 Subject: [PATCH] chore: use stats from tscommon --- src/frontend/statistics/graphStatistics.ts | 92 ------------- src/frontend/statistics/index.ts | 27 ---- .../statistics/tests/attributeStats.test.ts | 107 ---------------- .../statistics/tests/getAttributeType.test.ts | 65 ---------- .../statistics/tests/graphStatistics.test.ts | 121 ------------------ .../statistics/utils/attributeStats/array.ts | 6 - .../utils/attributeStats/boolean.ts | 9 -- .../utils/attributeStats/categorical.ts | 15 --- .../statistics/utils/attributeStats/index.ts | 7 - .../utils/attributeStats/initialize.ts | 47 ------- .../utils/attributeStats/numerical.ts | 9 -- .../statistics/utils/attributeStats/object.ts | 5 - .../utils/attributeStats/temporal.ts | 10 -- .../statistics/utils/getAttributeType.ts | 78 ----------- src/frontend/statistics/utils/index.ts | 3 - .../statistics/utils/updateStatistics.ts | 45 ------- src/readers/queryService.ts | 6 +- 17 files changed, 2 insertions(+), 650 deletions(-) delete mode 100644 src/frontend/statistics/graphStatistics.ts delete mode 100644 src/frontend/statistics/index.ts delete mode 100644 src/frontend/statistics/tests/attributeStats.test.ts delete mode 100644 src/frontend/statistics/tests/getAttributeType.test.ts delete mode 100644 src/frontend/statistics/tests/graphStatistics.test.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/array.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/boolean.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/categorical.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/index.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/initialize.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/numerical.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/object.ts delete mode 100644 src/frontend/statistics/utils/attributeStats/temporal.ts delete mode 100644 src/frontend/statistics/utils/getAttributeType.ts delete mode 100644 src/frontend/statistics/utils/index.ts delete mode 100644 src/frontend/statistics/utils/updateStatistics.ts diff --git a/src/frontend/statistics/graphStatistics.ts b/src/frontend/statistics/graphStatistics.ts deleted file mode 100644 index 904223d..0000000 --- a/src/frontend/statistics/graphStatistics.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { GraphQueryResultFromBackend, GraphStatistics } from 'ts-common'; -import { getAttributeType, initializeStatistics, updateStatistics } from './utils'; - -export const getGraphStatistics = (graph: GraphQueryResultFromBackend): GraphStatistics => { - const { nodes, edges } = graph; - - const n_nodes = nodes.length; - const n_edges = edges.length; - - const density = n_nodes < 2 ? 0 : (n_edges * 2) / (n_nodes * (n_nodes - 1)); - - // general nodes and edges statistics - const metaData: GraphStatistics = { - topological: { density, self_loops: 0 }, - nodes: { labels: [], count: n_nodes, types: {} }, - edges: { labels: [], count: n_edges, types: {} }, - }; - // return metaData; - - // attributes based statistics - // Pre-initialize maps for faster lookups - const seenNodeTypes = new Set(); - - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - const nodeType = node.label; - - // Use Set for faster existence checks - if (!seenNodeTypes.has(nodeType)) { - seenNodeTypes.add(nodeType); - metaData.nodes.labels.push(nodeType); - metaData.nodes.types[nodeType] = { count: 0, attributes: {} }; - } - - const nodeTypeStats = metaData.nodes.types[nodeType]; - nodeTypeStats.count++; - - const attributes = node.attributes; - const nodeTypeAttributes = nodeTypeStats.attributes; - - const attributeEntries = Object.entries(attributes); - for (let j = 0; j < attributeEntries.length; j++) { - const [attributeId, attributeValue] = attributeEntries[j]; - if (!nodeTypeAttributes[attributeId]) { - const attributeType = getAttributeType(attributeValue); - nodeTypeAttributes[attributeId] = { - attributeType, - statistics: initializeStatistics(attributeType), - }; - } - updateStatistics(nodeTypeAttributes[attributeId], attributeValue); - } - } - - // Process edges - // Pre-initialize sets and maps for faster lookups - const seenEdgeTypes = new Set(); - - for (let i = 0; i < edges.length; i++) { - const edge = edges[i]; - const edgeType = edge.label; - - // Use Set for faster existence checks - if (!seenEdgeTypes.has(edgeType)) { - seenEdgeTypes.add(edgeType); - metaData.edges.labels.push(edgeType); - metaData.edges.types[edgeType] = { count: 0, attributes: {} }; - } - - metaData.edges.types[edgeType].count++; - - if (edge.from === edge.to) metaData.topological.self_loops++; - - const edgeTypeAttributes = metaData.edges.types[edgeType].attributes; - const attributes = edge.attributes; - - const attributeEntries = Object.entries(attributes); - for (let i = 0; i < attributeEntries.length; i++) { - const [attributeId, attributeValue] = attributeEntries[i]; - if (!edgeTypeAttributes[attributeId]) { - const attributeType = getAttributeType(attributeValue); - edgeTypeAttributes[attributeId] = { - attributeType, - statistics: initializeStatistics(attributeType), - }; - } - updateStatistics(edgeTypeAttributes[attributeId], attributeValue); - } - } - - return metaData; -}; diff --git a/src/frontend/statistics/index.ts b/src/frontend/statistics/index.ts deleted file mode 100644 index 2d2a10f..0000000 --- a/src/frontend/statistics/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { EdgeQueryResult, GraphQueryResultFromBackend, GraphQueryResultMetaFromBackend, NodeQueryResult } from 'ts-common'; -import { getGraphStatistics } from './graphStatistics'; - -export * from './graphStatistics'; - -export const graphQueryBackend2graphQuery = (payload: GraphQueryResultFromBackend): GraphQueryResultMetaFromBackend => { - const nodeIDs = new Set(); - const edgeIDs = new Set(); - - // Assign ids to a hidden attribute _id to better identify them - for (let i = 0; i < payload.nodes.length; i++) { - payload.nodes[i]._id = payload.nodes[i]._id || (payload.nodes[i] as any).id; - nodeIDs.add(payload.nodes[i]._id); - } - for (let i = 0; i < payload.edges.length; i++) { - payload.edges[i]._id = payload.edges[i]._id || (payload.edges[i] as any).id; - edgeIDs.add(payload.edges[i]._id); - } - - // Only keep one node and one edge per id. This is also done in the backend, but we do it here as well to be sure. - const nodes = [...nodeIDs].map(nodeID => payload.nodes.find(node => node._id === nodeID) as unknown as NodeQueryResult); - const edges = [...edgeIDs].map(edgeID => payload.edges.find(edge => edge._id === edgeID) as unknown as EdgeQueryResult); - - const metaData = getGraphStatistics(payload); - - return { metaData, nodes, edges }; -}; diff --git a/src/frontend/statistics/tests/attributeStats.test.ts b/src/frontend/statistics/tests/attributeStats.test.ts deleted file mode 100644 index 17f3093..0000000 --- a/src/frontend/statistics/tests/attributeStats.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { describe, it, expect } from 'bun:test'; -import { - updateArrayStats, - updateBooleanStats, - updateCategoricalStats, - updateNumericalStats, - updateTemporalStats, - updateObjectStats, - initializeStatistics, -} from '../utils/attributeStats'; -import type { ArrayStats, BooleanStats, CategoricalStats, NumericalStats, TemporalStats, ObjectStats } from 'ts-common'; - -describe('updateArrayStats', () => { - it('should update the length of the array', () => { - const stats: ArrayStats = { length: 0, count: 0 }; - const value = [1, 2, 3]; - updateArrayStats(stats, value); - expect(stats.length).toBe(3); - expect(stats.count).toBe(1); - }); -}); - -describe('updateBooleanStats', () => { - it('should update true count when value is true', () => { - const stats: BooleanStats = { true: 0, false: 0 }; - updateBooleanStats(stats, true); - expect(stats.true).toBe(1); - expect(stats.false).toBe(0); - }); - - it('should update false count when value is false', () => { - const stats: BooleanStats = { true: 0, false: 0 }; - updateBooleanStats(stats, false); - expect(stats.false).toBe(1); - expect(stats.true).toBe(0); - }); -}); - -describe('updateCategoricalStats', () => { - it('should update mode and unique items count', () => { - const stats: CategoricalStats = { uniqueItems: 0, values: [], mode: '', count: 0 }; - updateCategoricalStats(stats, 'apple'); - updateCategoricalStats(stats, 'banana'); - updateCategoricalStats(stats, 'apple'); - - expect(stats.values).toEqual(['apple', 'banana', 'apple']); - expect(stats.uniqueItems).toBe(2); - expect(stats.mode).toBe('apple'); - expect(stats.count).toBe(3); - }); -}); - -describe('updateNumericalStats', () => { - it('should update min, max, average, and count', () => { - const stats: NumericalStats = { min: Infinity, max: -Infinity, average: 0, count: 0 }; - updateNumericalStats(stats, 10); - updateNumericalStats(stats, 20); - updateNumericalStats(stats, 5); - - expect(stats.min).toBe(5); - expect(stats.max).toBe(20); - expect(stats.average).toBeCloseTo(11.67, 2); - expect(stats.count).toBe(3); - }); -}); - -describe('updateTemporalStats', () => { - it('should update min, max, and range for temporal values', () => { - const stats: TemporalStats = { min: Infinity, max: -Infinity, range: 0 }; - updateTemporalStats(stats, '2022-01-01'); - updateTemporalStats(stats, '2022-01-05'); - - expect(stats.min).toBe(new Date('2022-01-01').getTime()); - expect(stats.max).toBe(new Date('2022-01-05').getTime()); - expect(stats.range).toBe(new Date('2022-01-05').getTime() - new Date('2022-01-01').getTime()); - }); -}); - -describe('updateObjectStats', () => { - it('should update the length of the object keys', () => { - const stats: ObjectStats = { length: 0 }; - const value = { key1: 'value1', key2: 'value2' }; - updateObjectStats(stats, value); - expect(stats.length).toBe(2); - }); -}); - -describe('initializeStatistics', () => { - it('should initialize statistics for string type', () => { - const stats = initializeStatistics('string'); - expect(stats).toEqual({ uniqueItems: 0, values: [], mode: '', count: 0 }); - }); - - it('should initialize statistics for boolean type', () => { - const stats = initializeStatistics('boolean'); - expect(stats).toEqual({ true: 0, false: 0 }); - }); - - it('should initialize statistics for number type', () => { - const stats = initializeStatistics('number'); - expect(stats).toEqual({ min: Infinity, max: -Infinity, average: 0, count: 0 }); - }); - - it('should throw an error for an unknown type', () => { - expect(() => initializeStatistics('unknown' as any)).toThrow('Unknown attribute type: unknown'); - }); -}); diff --git a/src/frontend/statistics/tests/getAttributeType.test.ts b/src/frontend/statistics/tests/getAttributeType.test.ts deleted file mode 100644 index 6b8923c..0000000 --- a/src/frontend/statistics/tests/getAttributeType.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { describe, it, expect } from 'bun:test'; -import { getAttributeType } from '../utils/getAttributeType'; - -// Sample values for testing -const invalidDate = '2023-13-03'; -const validTime = '12:30:45'; -const invalidTime = '25:61:61'; -const invalidDatetime = '2023-10-03 25:61:61'; -const validNumber = '123.45'; -const invalidNumber = 'abc123'; -const booleanTrue = true; -const booleanFalse = false; -const numberValue = 123; -const arrayValue = [1, 2, 3]; -const objectValue = { key: 'value' }; -const dateInstance = new Date('2023-10-03T12:30:45'); - -// Unit tests for getAttributeType function -describe('getAttributeType', () => { - it('should correctly identify numbers as type "number"', () => { - expect(getAttributeType(validNumber)).toBe('number'); - expect(getAttributeType(numberValue)).toBe('number'); - }); - - it('should correctly identify strings as valid "time"', () => { - expect(getAttributeType(validTime)).toBe('time'); - }); - - it('should identify invalid datetime strings as "string"', () => { - expect(getAttributeType(invalidDatetime)).toBe('string'); - }); - - it('should identify invalid date strings as "string"', () => { - expect(getAttributeType(invalidDate)).toBe('string'); - }); - - it('should identify invalid time strings as "string"', () => { - expect(getAttributeType(invalidTime)).toBe('string'); - }); - - it('should correctly identify boolean values as type "boolean"', () => { - expect(getAttributeType(booleanTrue)).toBe('boolean'); - expect(getAttributeType(booleanFalse)).toBe('boolean'); - }); - - it('should correctly identify arrays as type "array"', () => { - expect(getAttributeType(arrayValue)).toBe('array'); - }); - - it('should correctly identify objects as type "object"', () => { - expect(getAttributeType(objectValue)).toBe('object'); - }); - - it('should correctly identify Date instances as type "datetime"', () => { - expect(getAttributeType(dateInstance)).toBe('datetime'); - }); - - it('should identify string representations of invalid numbers as "string"', () => { - expect(getAttributeType(invalidNumber)).toBe('string'); - }); - - it('should identify a regular string as type "string"', () => { - expect(getAttributeType('random string')).toBe('string'); - }); -}); diff --git a/src/frontend/statistics/tests/graphStatistics.test.ts b/src/frontend/statistics/tests/graphStatistics.test.ts deleted file mode 100644 index f2b912e..0000000 --- a/src/frontend/statistics/tests/graphStatistics.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { describe, it, expect } from 'bun:test'; -import { getGraphStatistics } from '../graphStatistics'; -import type { GraphQueryResultFromBackend } from 'ts-common'; - -describe('getGraphStatistics', () => { - it('should return correct statistics for a graph with no nodes and edges', () => { - const graph: GraphQueryResultFromBackend = { - nodes: [], - edges: [], - }; - - const stats = getGraphStatistics(graph); - - expect(stats).toEqual({ - topological: { density: 0, self_loops: 0 }, - nodes: { labels: [], count: 0, types: {} }, - edges: { labels: [], count: 0, types: {} }, - }); - }); - - it('should return correct statistics for a graph with nodes and no edges', () => { - const graph: GraphQueryResultFromBackend = { - nodes: [ - { _id: '1', label: 'Person', attributes: { age: 25 } }, - { _id: '2', label: 'Person', attributes: { age: 30, city: 'New York' } }, - ], - edges: [], - }; - - const stats = getGraphStatistics(graph); - - expect(stats).toEqual({ - topological: { density: 0, self_loops: 0 }, - nodes: { - labels: ['Person'], // Assuming default label - count: 2, - types: { - Person: { - count: 2, - attributes: { - age: { attributeType: 'number', statistics: expect.any(Object) }, - city: { attributeType: 'string', statistics: expect.any(Object) }, - }, - }, - }, - }, - edges: { labels: [], count: 0, types: {} }, - }); - }); - - it('should return correct statistics for a graph with edges and nodes', () => { - const graph: GraphQueryResultFromBackend = { - nodes: [ - { _id: '1', label: 'Person', attributes: { age: 25 } }, - { _id: '2', label: 'Person', attributes: { age: 30 } }, - ], - edges: [ - { _id: 'e1', label: 'Relationship', attributes: { weight: 5 }, from: '1', to: '2' }, - { _id: 'e2', label: 'Relationship', attributes: { weight: 10 }, from: '2', to: '2' }, // self-loop - ], - }; - - const stats = getGraphStatistics(graph); - - expect(stats).toEqual({ - topological: { density: 2, self_loops: 1 }, - nodes: { - labels: ['Person'], // Assuming default label - count: 2, - types: { - Person: { - count: 2, - attributes: { - age: { attributeType: 'number', statistics: expect.any(Object) }, - }, - }, - }, - }, - edges: { - labels: ['Relationship'], // Assuming default edge type - count: 2, - types: { - Relationship: { - count: 2, - attributes: { - weight: { attributeType: 'number', statistics: expect.any(Object) }, - }, - }, - }, - }, - }); - }); - - it('should correctly count self-loops', () => { - const graph: GraphQueryResultFromBackend = { - nodes: [{ _id: '1', attributes: {}, label: 'Person' }], - edges: [ - { _id: 'e1', attributes: {}, from: '1', to: '1', label: 'TO_PERSON' }, // self-loop - ], - }; - - const stats = getGraphStatistics(graph); - - expect(stats.topological.self_loops).toBe(1); - }); - - it('should correctly compute density for a graph with nodes and edges', () => { - const graph: GraphQueryResultFromBackend = { - nodes: [ - { _id: '1', attributes: {}, label: 'Person' }, - { _id: '2', attributes: {}, label: 'Person' }, - ], - edges: [{ _id: 'e1', attributes: {}, from: '1', to: '2', label: 'TO_PERSON' }], - }; - - const stats = getGraphStatistics(graph); - - // Density = (n_edges * 2) / (n_nodes * (n_nodes - 1)) = (1 * 2) / (2 * 1) = 1 - expect(stats.topological.density).toBe(1); - }); -}); diff --git a/src/frontend/statistics/utils/attributeStats/array.ts b/src/frontend/statistics/utils/attributeStats/array.ts deleted file mode 100644 index 1845238..0000000 --- a/src/frontend/statistics/utils/attributeStats/array.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { ArrayStats } from 'ts-common'; - -export const updateArrayStats = (stats: ArrayStats, value: any[]) => { - stats.length = value.length; - stats.count++; -}; diff --git a/src/frontend/statistics/utils/attributeStats/boolean.ts b/src/frontend/statistics/utils/attributeStats/boolean.ts deleted file mode 100644 index a737e97..0000000 --- a/src/frontend/statistics/utils/attributeStats/boolean.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { BooleanStats } from 'ts-common'; - -export const updateBooleanStats = (stats: BooleanStats, value: boolean) => { - if (value) { - stats.true += 1; - } else { - stats.false += 1; - } -}; diff --git a/src/frontend/statistics/utils/attributeStats/categorical.ts b/src/frontend/statistics/utils/attributeStats/categorical.ts deleted file mode 100644 index 860cda7..0000000 --- a/src/frontend/statistics/utils/attributeStats/categorical.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { CategoricalStats } from 'ts-common'; - -export const updateCategoricalStats = (stats: CategoricalStats, value: string | boolean) => { - if (!stats.values) stats.values = []; - stats.values.push(value.toString()); - - stats.uniqueItems = new Set(stats.values).size; - - const frequencyMap: { [key: string]: number } = {}; - stats.values.forEach(val => { - frequencyMap[val] = (frequencyMap[val] || 0) + 1; - }); - stats.mode = Object.keys(frequencyMap).reduce((a, b) => (frequencyMap[a] > frequencyMap[b] ? a : b)); - stats.count++; -}; diff --git a/src/frontend/statistics/utils/attributeStats/index.ts b/src/frontend/statistics/utils/attributeStats/index.ts deleted file mode 100644 index 42c4501..0000000 --- a/src/frontend/statistics/utils/attributeStats/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './array'; -export * from './categorical'; -export * from './numerical'; -export * from './object'; -export * from './temporal'; -export * from './boolean'; -export * from './initialize'; diff --git a/src/frontend/statistics/utils/attributeStats/initialize.ts b/src/frontend/statistics/utils/attributeStats/initialize.ts deleted file mode 100644 index d4431b4..0000000 --- a/src/frontend/statistics/utils/attributeStats/initialize.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { AttributeType, AttributeTypeStats } from 'ts-common'; - -const initializeStatistics = <T extends AttributeType>(type: T): AttributeTypeStats<T> => { - switch (type) { - case 'string': - return { - uniqueItems: 0, - values: [], - mode: '', - count: 0, - } as unknown as AttributeTypeStats<T>; - case 'boolean': - return { - true: 0, - false: 0, - } as unknown as AttributeTypeStats<T>; - case 'number': - return { - min: Infinity, - max: -Infinity, - average: 0, - count: 0, - } as unknown as AttributeTypeStats<T>; - case 'date': - case 'time': - case 'datetime': - case 'timestamp': - return { - min: Infinity, - max: -Infinity, - range: 0, - } as unknown as AttributeTypeStats<T>; - case 'array': - return { - length: 0, - count: 0, - } as unknown as AttributeTypeStats<T>; - case 'object': - return { - length: 0, - } as unknown as AttributeTypeStats<T>; - default: - throw new Error(`Unknown attribute type: ${type}`); - } -}; - -export { initializeStatistics }; diff --git a/src/frontend/statistics/utils/attributeStats/numerical.ts b/src/frontend/statistics/utils/attributeStats/numerical.ts deleted file mode 100644 index d0a68b5..0000000 --- a/src/frontend/statistics/utils/attributeStats/numerical.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { NumericalStats } from 'ts-common'; - -export const updateNumericalStats = (stats: NumericalStats, value: number) => { - if (stats.min === undefined || value < stats.min) stats.min = value; - if (stats.max === undefined || value > stats.max) stats.max = value; - - stats.count++; - stats.average = (stats.average * (stats.count - 1) + value) / stats.count; -}; diff --git a/src/frontend/statistics/utils/attributeStats/object.ts b/src/frontend/statistics/utils/attributeStats/object.ts deleted file mode 100644 index 46e60f2..0000000 --- a/src/frontend/statistics/utils/attributeStats/object.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { ObjectStats } from 'ts-common'; - -export const updateObjectStats = (stats: ObjectStats, value: object) => { - stats.length = Object.keys(value).length; -}; diff --git a/src/frontend/statistics/utils/attributeStats/temporal.ts b/src/frontend/statistics/utils/attributeStats/temporal.ts deleted file mode 100644 index 49e1b3e..0000000 --- a/src/frontend/statistics/utils/attributeStats/temporal.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { TemporalStats } from 'ts-common'; - -export const updateTemporalStats = (stats: TemporalStats, value: string | Date) => { - const timestamp = value instanceof Date ? value.getTime() : new Date(value).getTime(); - - if (stats.min === undefined || timestamp < stats.min) stats.min = timestamp; - if (stats.max === undefined || timestamp > stats.max) stats.max = timestamp; - - stats.range = stats.max - stats.min; -}; diff --git a/src/frontend/statistics/utils/getAttributeType.ts b/src/frontend/statistics/utils/getAttributeType.ts deleted file mode 100644 index bb3f968..0000000 --- a/src/frontend/statistics/utils/getAttributeType.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { AttributeType } from 'ts-common'; - -// Check if a string is a valid date in the YYYY-MM-DD format -const isValidDate = (value: string): boolean => { - const dateRegex = /^\d{4}-\d{2}-\d{2}$/; // Matches YYYY-MM-DD format - const [year, month, day] = value.split('-').map(Number); - const date = new Date(value); - - // Check if the regex matches, and if the date is valid (correct month/day conversion) - return ( - dateRegex.test(value) && - date.getFullYear() === year && - date.getMonth() + 1 === month && // Months are 0-based in JS Date - date.getDate() === day - ); -}; - -// Check if a string is a valid time in the hh:mm:ss format -const isValidTime = (value: string): boolean => { - const timeRegex = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/; - return timeRegex.test(value); -}; - -// Check if a string is a valid datetime in the YYYY-MM-DD hh:mm:ss format -const isValidDatetime = (value: string): boolean => { - const datetimeRegex = /^\d{4}-\d{2}-\d{2} ([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/; - const [date, time] = value.split(' '); - - return datetimeRegex.test(value) && isValidDate(date) && isValidTime(time); -}; - -// Check if a string is a valid number -const isValidNumber = (value: string): boolean => { - return !isNaN(Number(value)) && !isNaN(parseFloat(value)); -}; - -// Determines the type of an attribute -const getAttributeType = (value: any): AttributeType => { - if (typeof value === 'string') { - if (isValidNumber(value)) { - return 'number'; - } - if (isValidDatetime(value)) { - return 'datetime'; - } - if (isValidDate(value)) { - return 'date'; - } - if (isValidTime(value)) { - return 'time'; - } - return 'string'; - } - - if (typeof value === 'boolean') { - return 'boolean'; - } - - if (typeof value === 'number') { - return 'number'; - } - - if (Array.isArray(value)) { - return 'array'; - } - - if (value instanceof Date) { - return 'datetime'; - } - - if (typeof value === 'object' && value !== null) { - return 'object'; - } - - return 'string'; -}; - -export { getAttributeType }; diff --git a/src/frontend/statistics/utils/index.ts b/src/frontend/statistics/utils/index.ts deleted file mode 100644 index 4fb895d..0000000 --- a/src/frontend/statistics/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './getAttributeType'; -export * from './attributeStats'; -export * from './updateStatistics'; diff --git a/src/frontend/statistics/utils/updateStatistics.ts b/src/frontend/statistics/utils/updateStatistics.ts deleted file mode 100644 index 03a49de..0000000 --- a/src/frontend/statistics/utils/updateStatistics.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { - ArrayStats, - AttributeStats, - AttributeType, - BooleanStats, - CategoricalStats, - NumericalStats, - ObjectStats, - TemporalStats, -} from 'ts-common'; -import { - updateArrayStats, - updateCategoricalStats, - updateNumericalStats, - updateObjectStats, - updateTemporalStats, - updateBooleanStats, -} from './attributeStats'; - -// Update statistics based on attribute type and value -export const updateStatistics = (attribute: AttributeStats<AttributeType>, value: any) => { - switch (attribute.attributeType) { - case 'number': - updateNumericalStats(attribute.statistics as NumericalStats, value); - break; - case 'string': - updateCategoricalStats(attribute.statistics as CategoricalStats, value); - break; - case 'boolean': - updateBooleanStats(attribute.statistics as BooleanStats, value); - break; - case 'datetime': - case 'timestamp': - case 'date': - case 'time': - updateTemporalStats(attribute.statistics as TemporalStats, value); - break; - case 'array': - updateArrayStats(attribute.statistics as ArrayStats, value); - break; - case 'object': - updateObjectStats(attribute.statistics as ObjectStats, value); - break; - } -}; diff --git a/src/readers/queryService.ts b/src/readers/queryService.ts index 5fa9526..448459b 100644 --- a/src/readers/queryService.ts +++ b/src/readers/queryService.ts @@ -1,4 +1,4 @@ -import { type DbConnection, type QueryRequest } from 'ts-common'; +import { graphQueryBackend2graphQuery, type DbConnection, type QueryRequest } from 'ts-common'; import { rabbitMq, redis, ums, type QueryExecutionTypes } from '../variables'; import { log } from '../logger'; @@ -6,11 +6,9 @@ import { QueryPublisher } from '../utils/queryPublisher'; import { query2Cypher } from '../utils/cypher/converter'; import { parseCypherQuery } from '../utils/cypher/queryParser'; import { formatTimeDifference } from 'ts-common/src/logger/logger'; -import { graphQueryBackend2graphQuery } from '../frontend/statistics'; import { Query2BackendQuery } from '../utils/reactflow/query2backend'; -import type { GraphQueryResultMetaFromBackend } from 'ts-common/src/model/webSocket/graphResult'; +import type { GraphQueryResultFromBackend, GraphQueryResultMetaFromBackend } from 'ts-common/src/model/webSocket/graphResult'; import { RabbitMqBroker } from 'ts-common/rabbitMq'; -import { RedisConnector } from 'ts-common/redis'; import { Neo4jConnection } from 'ts-common/neo4j'; export const queryService = async (db: DbConnection, query: string): Promise<GraphQueryResultMetaFromBackend> => { -- GitLab