Skip to content

Commit 9ee95be

Browse files
committed
fix docs for new changes in Query runner class
1 parent 5baf259 commit 9ee95be

File tree

1 file changed

+92
-21
lines changed

1 file changed

+92
-21
lines changed

QueryRunner-Usage-Guide.md

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@ API Request → QueryRunner → [MongoDB|ClickHouse|Future Adapters]
1818

1919
## Query Definition Structure
2020

21+
```typescript
22+
interface QueryDefinition<TParams = unknown, TResult = unknown> {
23+
name: string; // Unique identifier for logging/debugging
24+
adapters: {
25+
mongodb?: AdapterConfig<TParams, TResult>;
26+
clickhouse?: AdapterConfig<TParams, TResult>;
27+
};
28+
}
29+
30+
interface AdapterConfig<TParams = unknown, TResult = unknown> {
31+
handler: QueryHandler<TParams, TResult>;
32+
transform?: TransformFunction<TResult>;
33+
available?: boolean; // Optional, defaults to true
34+
}
35+
```
36+
37+
**Example implementation:**
2138
```javascript
2239
const queryDef = {
2340
name: 'QUERY_NAME', // Unique identifier for logging/debugging
@@ -33,9 +50,8 @@ const queryDef = {
3350

3451
return {
3552
_queryMeta: {
36-
type: 'mongodb',
37-
query: pipeline,
38-
collection: 'events' // Optional: additional metadata
53+
adapter: 'mongodb', // Required: adapter name
54+
query: pipeline // Required: actual executed query
3955
},
4056
data: result
4157
};
@@ -54,15 +70,16 @@ const queryDef = {
5470

5571
return {
5672
_queryMeta: {
57-
type: 'clickhouse',
58-
query: sql
73+
adapter: 'clickhouse', // Required: adapter name
74+
query: sql // Required: actual executed query
5975
},
6076
data: result.data
6177
};
6278
},
63-
transform: async (result, transformOptions) => {
79+
transform: async (data, transformOptions) => {
6480
// Transform ClickHouse results to match expected format
65-
return result.data.map(row => ({
81+
// Note: transform receives only the data portion, not full result
82+
return data.map(row => ({
6683
total: parseInt(row.total) || 0
6784
}));
6885
},
@@ -74,18 +91,34 @@ const queryDef = {
7491

7592
### Handler Requirements
7693

94+
**TypeScript Signature:**
95+
```typescript
96+
type QueryHandler<TParams = unknown, TResult = unknown> = (
97+
params: TParams,
98+
options?: ExecutionOptions
99+
) => Promise<QueryResult<TResult>>;
100+
101+
interface QueryResult<TData = unknown> {
102+
_queryMeta: QueryMeta;
103+
data: TData;
104+
}
105+
106+
interface QueryMeta {
107+
adapter: AdapterName; // 'mongodb' | 'clickhouse'
108+
query: unknown; // The actual query/pipeline executed
109+
}
110+
```
111+
77112
**Input Parameters:**
78113
- `params`: Query-specific parameters (app_id, date ranges, filters, etc.)
79-
- `options` *(optional)*: Execution options (timeout, connection settings, etc.)
114+
- `options` *(optional)*: ExecutionOptions (adapter, comparison mode, etc.)
80115

81116
**Required Output Structure:**
82117
```javascript
83118
{
84119
_queryMeta: {
85-
type: 'mongodb' | 'clickhouse', // Adapter type
86-
query: actualQuery, // Executed query (pipeline/SQL) for debugging
87-
collection?: string, // Optional: MongoDB collection name
88-
// Add any other optional metadata fields as needed
120+
adapter: 'mongodb' | 'clickhouse', // Required: adapter name
121+
query: actualQuery // Required: executed query for debugging
89122
},
90123
data: queryResults // Raw query results
91124
}
@@ -96,9 +129,17 @@ const queryDef = {
96129
Each adapter can optionally define a transform function to normalize or process results:
97130

98131
**Transform Function Signature:**
132+
```typescript
133+
type TransformFunction<TInput = unknown, TOutput = unknown> = (
134+
data: TInput,
135+
transformOptions?: Record<string, unknown>
136+
) => Promise<TOutput>;
137+
```
138+
139+
**Implementation:**
99140
```javascript
100-
transform: async (result, transformOptions) => {
101-
// result: Full handler result with _queryMeta and data
141+
transform: async (data, transformOptions) => {
142+
// data: Only the data portion from handler result (not full QueryResult)
102143
// transformOptions: Configuration object passed from executeQuery
103144
return transformedData;
104145
}
@@ -109,12 +150,14 @@ transform: async (result, transformOptions) => {
109150
- Transform functions should be lightweight and focused
110151
- Handle data type differences (e.g., string to number conversion)
111152
- MongoDB adapters often don't need transforms if data is already normalized
153+
- Transform receives only the `data` portion, not the full `QueryResult` object
112154

113155
#### Handler Best Practices
114-
- Always include `_queryMeta` with actual executed query for debugging
156+
- Always include `_queryMeta` with `adapter` name and actual executed `query` for debugging
115157
- Return consistent data structure across adapters when possible
116158
- Handle errors gracefully and let them bubble up
117-
- Use `options` parameter for adapter-specific settings
159+
- Use `options` parameter for execution-related settings (not adapter-specific configs)
160+
- Follow TypeScript interfaces for type safety
118161

119162
## Comparison Mode
120163

@@ -140,25 +183,53 @@ const result = await queryRunner.executeQuery(queryDef, params, { comparison: tr
140183
const QueryRunner = require('./api/parts/data/QueryRunner.js');
141184
common.queryRunner = new QueryRunner();
142185

143-
// Normal execution
186+
// Normal execution - returns only transformed data, not full QueryResult
144187
const result = await common.queryRunner.executeQuery(queryDef, params);
145188

146189
// Force specific adapter
147190
const result = await common.queryRunner.executeQuery(queryDef, params, { adapter: 'clickhouse' });
148191

149-
// Comparison mode
192+
// Comparison mode - logs detailed comparison data to files
150193
const result = await common.queryRunner.executeQuery(queryDef, params, { comparison: true });
151194

152195
// With transform options
153196
const transformOptions = { dateFormat: 'ISO', includeMetadata: true };
154197
const result = await common.queryRunner.executeQuery(queryDef, params, {}, transformOptions);
155198
```
156199

200+
### TypeScript Usage
201+
202+
```typescript
203+
import QueryRunner, { QueryDefinition, ExecutionOptions } from './types/QueryRunner';
204+
205+
// Type-safe query definition
206+
const queryDef: QueryDefinition<{app_id: string}, {total: number}[]> = {
207+
name: 'GET_EVENT_TOTALS',
208+
adapters: {
209+
mongodb: {
210+
handler: async (params, options) => {
211+
// Implementation with type safety
212+
return {
213+
_queryMeta: { adapter: 'mongodb', query: pipeline },
214+
data: results
215+
};
216+
}
217+
}
218+
}
219+
};
220+
221+
// Type-safe execution
222+
const result: {total: number}[] = await queryRunner.executeQuery(queryDef, { app_id: 'test' });
223+
```
224+
157225
## Best Practices
158226

159-
1. Always implement `_queryMeta` for debugging
160-
2. Use adapter-specific transforms only when data formats differ between adapters
227+
1. Always implement `_queryMeta` with correct `adapter` name and `query` fields
228+
2. Use adapter-specific transforms only when data formats differ between adapters
161229
3. Keep transform functions lightweight and focused on format normalization
162230
4. Test with comparison mode during development to validate adapter consistency
163231
5. Monitor debug timing logs for performance issues
164-
6. Prefer normalizing data in handlers over complex transforms when possible
232+
6. Prefer normalizing data in handlers over complex transforms when possible
233+
7. Use TypeScript definitions for type safety and better IDE support
234+
8. Remember that `executeQuery` returns only the transformed data, not the full `QueryResult`
235+
9. Transform functions receive only the `data` portion, not the complete handler result

0 commit comments

Comments
 (0)