@trafficgroup/knex-rel 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dao/VideoMinuteResultDAO.d.ts +0 -4
- package/dist/dao/VideoMinuteResultDAO.js +7 -48
- package/dist/dao/VideoMinuteResultDAO.js.map +1 -1
- package/dist/dao/camera/camera.dao.d.ts +0 -2
- package/dist/dao/camera/camera.dao.js +0 -42
- package/dist/dao/camera/camera.dao.js.map +1 -1
- package/dist/dao/report-configuration/report-configuration.dao.d.ts +94 -0
- package/dist/dao/report-configuration/report-configuration.dao.js +352 -0
- package/dist/dao/report-configuration/report-configuration.dao.js.map +1 -0
- package/dist/dao/video/video.dao.d.ts +0 -3
- package/dist/dao/video/video.dao.js +4 -43
- package/dist/dao/video/video.dao.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/report-configuration/report-configuration.interfaces.d.ts +26 -0
- package/dist/interfaces/report-configuration/report-configuration.interfaces.js +3 -0
- package/dist/interfaces/report-configuration/report-configuration.interfaces.js.map +1 -0
- package/migrations/20250930200521_migration.ts +52 -0
- package/package.json +1 -1
- package/plan.md +950 -204
- package/src/dao/VideoMinuteResultDAO.ts +7 -64
- package/src/dao/camera/camera.dao.ts +0 -55
- package/src/dao/report-configuration/report-configuration.dao.ts +402 -0
- package/src/dao/video/video.dao.ts +4 -51
- package/src/index.ts +8 -0
- package/src/interfaces/report-configuration/report-configuration.interfaces.ts +30 -0
- package/cameras_analysis.md +0 -199
- package/folder_cameraid_analysis.md +0 -167
- package/migrations/20250924000000_camera_name_search_index.ts +0 -22
package/cameras_analysis.md
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
# Database Schema Analysis - Cameras Table Implementation
|
|
2
|
-
|
|
3
|
-
## Current Schema Analysis
|
|
4
|
-
|
|
5
|
-
### 1. Videos Table (Current Structure)
|
|
6
|
-
|
|
7
|
-
- **Table Name**: `video`
|
|
8
|
-
- **Primary Key**: `id` (auto-increment number)
|
|
9
|
-
- **UUID**: `uuid` (unique, not null) - for external references
|
|
10
|
-
- **Foreign Keys**:
|
|
11
|
-
- `folderId`: references `folders.id` (CASCADE delete)
|
|
12
|
-
- `cameraId`: references `cameras.id` (SET NULL on delete) ✅ **ALREADY EXISTS**
|
|
13
|
-
- `annotationSourceId`: self-reference to `video.id` (SET NULL)
|
|
14
|
-
- **Key Fields**:
|
|
15
|
-
- `videoLocation`: S3 path/URL for video file
|
|
16
|
-
- `videoRate`: frame rate (FPS)
|
|
17
|
-
- `videoType`: enum ['TMC', 'ATR', 'JUNCTION', 'ROUNDABOUT', 'PATHWAY']
|
|
18
|
-
- `status`: enum ['QUEUED', 'PROCESSING', 'COMPLETED', 'FAILED', 'PENDING']
|
|
19
|
-
- `metadata`: JSONB for lane annotations
|
|
20
|
-
- `results`: JSONB for processing results
|
|
21
|
-
- **Timestamps**: `created_at`, `updated_at`
|
|
22
|
-
- **Indexes**:
|
|
23
|
-
- `uuid` (unique)
|
|
24
|
-
- `cameraId`
|
|
25
|
-
- `annotationSourceId`
|
|
26
|
-
- Composite: `(folderId, videoType, status)`
|
|
27
|
-
|
|
28
|
-
### 2. Folders Table (Current Structure)
|
|
29
|
-
|
|
30
|
-
- **Table Name**: `folders`
|
|
31
|
-
- **Primary Key**: `id` (auto-increment number)
|
|
32
|
-
- **UUID**: `uuid` (unique, not null) - for external references
|
|
33
|
-
- **Foreign Keys**:
|
|
34
|
-
- `createdBy`: references `user.id` (CASCADE delete)
|
|
35
|
-
- `studyId`: references `study.id` (CASCADE delete)
|
|
36
|
-
- `cameraId`: references `cameras.id` (SET NULL on delete) ✅ **ALREADY EXISTS**
|
|
37
|
-
- **Key Fields**:
|
|
38
|
-
- `name`: folder name
|
|
39
|
-
- `status`: enum ['UPLOADING', 'COMPLETE']
|
|
40
|
-
- **Timestamps**: `created_at`, `updated_at`
|
|
41
|
-
- **Indexes**:
|
|
42
|
-
- `uuid` (unique)
|
|
43
|
-
- `cameraId`
|
|
44
|
-
|
|
45
|
-
### 3. Cameras Table (Current Structure) ✅ **ALREADY IMPLEMENTED**
|
|
46
|
-
|
|
47
|
-
- **Table Name**: `cameras`
|
|
48
|
-
- **Primary Key**: `id` (auto-increment number)
|
|
49
|
-
- **UUID**: `uuid` (unique, not null) - for external references
|
|
50
|
-
- **Fields**:
|
|
51
|
-
- `name`: string(100), not null
|
|
52
|
-
- `longitude`: decimal(10,7), not null
|
|
53
|
-
- `latitude`: decimal(10,7), not null
|
|
54
|
-
- **Timestamps**: `created_at`, `updated_at`
|
|
55
|
-
- **Indexes**:
|
|
56
|
-
- `uuid` (unique)
|
|
57
|
-
- Composite: `(longitude, latitude)` for geospatial queries
|
|
58
|
-
|
|
59
|
-
## Relationship Analysis
|
|
60
|
-
|
|
61
|
-
### Current Relationships ✅ **FULLY IMPLEMENTED**
|
|
62
|
-
|
|
63
|
-
1. **Study → Folders** (One-to-Many)
|
|
64
|
-
- Foreign key: `folders.studyId → study.id`
|
|
65
|
-
- Cascade delete: deleting study removes all folders
|
|
66
|
-
|
|
67
|
-
2. **Folders → Videos** (One-to-Many)
|
|
68
|
-
- Foreign key: `video.folderId → folders.id`
|
|
69
|
-
- Cascade delete: deleting folder removes all videos
|
|
70
|
-
|
|
71
|
-
3. **Cameras → Folders** (One-to-Many) ✅
|
|
72
|
-
- Foreign key: `folders.cameraId → cameras.id`
|
|
73
|
-
- SET NULL on delete: deleting camera keeps folders but removes reference
|
|
74
|
-
|
|
75
|
-
4. **Cameras → Videos** (One-to-Many) ✅
|
|
76
|
-
- Foreign key: `video.cameraId → cameras.id`
|
|
77
|
-
- SET NULL on delete: deleting camera keeps videos but removes reference
|
|
78
|
-
|
|
79
|
-
5. **Videos → Videos** (Self-Reference for Templates)
|
|
80
|
-
- Foreign key: `video.annotationSourceId → video.id`
|
|
81
|
-
- Used for lane annotation templates
|
|
82
|
-
|
|
83
|
-
## DAO Implementation Status
|
|
84
|
-
|
|
85
|
-
### CameraDAO ✅ **FULLY IMPLEMENTED**
|
|
86
|
-
|
|
87
|
-
- **File**: `src/dao/camera/camera.dao.ts`
|
|
88
|
-
- **Standard Methods**: create, getById, getByUuid, update, delete, getAll ✅
|
|
89
|
-
- **Custom Methods**:
|
|
90
|
-
- `getByName(name: string)`: Find camera by name ✅
|
|
91
|
-
- `getCamerasNearCoordinates(lng, lat, radius)`: Geospatial search using PostGIS ✅
|
|
92
|
-
- **Performance Features**: Uses PostGIS ST_DWithin for geographic queries ✅
|
|
93
|
-
|
|
94
|
-
### VideoDAO - Camera Integration ✅ **ALREADY INTEGRATED**
|
|
95
|
-
|
|
96
|
-
- **JOIN Queries**: Already includes folder data in getById/getByUuid ✅
|
|
97
|
-
- **Camera Support**: Interface includes `cameraId?: number` and `camera?: ICamera` ✅
|
|
98
|
-
- **Note**: DAO doesn't currently JOIN camera data, but interface supports it
|
|
99
|
-
|
|
100
|
-
### FolderDAO - Camera Integration ✅ **ALREADY INTEGRATED**
|
|
101
|
-
|
|
102
|
-
- **JOIN Queries**: Already includes study data in getById/getByUuid ✅
|
|
103
|
-
- **Camera Support**: Interface includes `cameraId?: number` and `camera?: ICamera` ✅
|
|
104
|
-
- **Note**: DAO doesn't currently JOIN camera data, but interface supports it
|
|
105
|
-
|
|
106
|
-
## Migration Status ✅ **COMPLETE**
|
|
107
|
-
|
|
108
|
-
**Migration**: `20250911000000_migration.ts` ✅ **ALREADY DEPLOYED**
|
|
109
|
-
|
|
110
|
-
- Creates `cameras` table with proper schema ✅
|
|
111
|
-
- Adds `cameraId` to `video` table with foreign key ✅
|
|
112
|
-
- Adds `cameraId` to `folders` table with foreign key ✅
|
|
113
|
-
- Proper indexes for performance ✅
|
|
114
|
-
- Safe rollback implementation ✅
|
|
115
|
-
|
|
116
|
-
## Interface Implementation Status ✅ **COMPLETE**
|
|
117
|
-
|
|
118
|
-
### ICamera ✅ **FULLY IMPLEMENTED**
|
|
119
|
-
|
|
120
|
-
- **File**: `src/interfaces/camera/camera.interfaces.ts`
|
|
121
|
-
- **Fields**: id, uuid, name, longitude, latitude, created_at, updated_at ✅
|
|
122
|
-
- **Export**: Properly exported in `src/index.ts` ✅
|
|
123
|
-
|
|
124
|
-
### IVideo ✅ **CAMERA INTEGRATION COMPLETE**
|
|
125
|
-
|
|
126
|
-
- **Camera Fields**: `cameraId?: number`, `camera?: ICamera` ✅
|
|
127
|
-
- **Relationships**: Imports ICamera interface ✅
|
|
128
|
-
|
|
129
|
-
### IFolder ✅ **CAMERA INTEGRATION COMPLETE**
|
|
130
|
-
|
|
131
|
-
- **Camera Fields**: `cameraId?: number`, `camera?: ICamera` ✅
|
|
132
|
-
- **Relationships**: Imports ICamera interface ✅
|
|
133
|
-
|
|
134
|
-
## Performance Considerations ✅ **OPTIMIZED**
|
|
135
|
-
|
|
136
|
-
### Database Indexes ✅
|
|
137
|
-
|
|
138
|
-
- `cameras.uuid` (unique) - for UUID lookups ✅
|
|
139
|
-
- `cameras(longitude, latitude)` - for geospatial queries ✅
|
|
140
|
-
- `video.cameraId` - for camera-to-videos lookups ✅
|
|
141
|
-
- `folders.cameraId` - for camera-to-folders lookups ✅
|
|
142
|
-
|
|
143
|
-
### Query Optimization ✅
|
|
144
|
-
|
|
145
|
-
- **VideoDAO**: Uses JOINs to eliminate N+1 queries (folder data) ✅
|
|
146
|
-
- **FolderDAO**: Uses JOINs to eliminate N+1 queries (study data) ✅
|
|
147
|
-
- **CameraDAO**: Geospatial queries use PostGIS for performance ✅
|
|
148
|
-
|
|
149
|
-
### Missing JOIN Optimizations (Minor Enhancement Opportunity)
|
|
150
|
-
|
|
151
|
-
- VideoDAO could JOIN camera data in getById/getByUuid queries
|
|
152
|
-
- FolderDAO could JOIN camera data in getById/getByUuid queries
|
|
153
|
-
- These would eliminate additional queries when camera data is needed
|
|
154
|
-
|
|
155
|
-
## System Architecture Compliance ✅
|
|
156
|
-
|
|
157
|
-
### Pattern Compliance ✅
|
|
158
|
-
|
|
159
|
-
- **Naming**: Follows `entityUuid` pattern for external references ✅
|
|
160
|
-
- **Timestamps**: Uses `created_at`/`updated_at` consistently ✅
|
|
161
|
-
- **Primary Keys**: Auto-increment `id` for internal use ✅
|
|
162
|
-
- **Foreign Keys**: Proper referential integrity with appropriate cascade rules ✅
|
|
163
|
-
|
|
164
|
-
### TypeScript Integration ✅
|
|
165
|
-
|
|
166
|
-
- **Type Safety**: Full TypeScript interfaces with proper typing ✅
|
|
167
|
-
- **Optional Fields**: Camera relationships marked as optional ✅
|
|
168
|
-
- **Export Structure**: All entities properly exported from main index ✅
|
|
169
|
-
|
|
170
|
-
## Current Implementation Status: ✅ **COMPLETE**
|
|
171
|
-
|
|
172
|
-
### What's Already Working:
|
|
173
|
-
|
|
174
|
-
1. **Database Schema**: Cameras table exists with proper relationships ✅
|
|
175
|
-
2. **Migrations**: All database changes deployed ✅
|
|
176
|
-
3. **DAOs**: CameraDAO fully implemented with geospatial features ✅
|
|
177
|
-
4. **Interfaces**: All TypeScript interfaces support camera relationships ✅
|
|
178
|
-
5. **Exports**: All components properly exported ✅
|
|
179
|
-
6. **Relationships**: Many-to-one relationships correctly implemented ✅
|
|
180
|
-
7. **Performance**: Proper indexing for UUID and geospatial queries ✅
|
|
181
|
-
|
|
182
|
-
### Minor Optimization Opportunities:
|
|
183
|
-
|
|
184
|
-
1. **JOIN Queries**: VideoDAO and FolderDAO could include camera data in their JOIN queries
|
|
185
|
-
2. **Query Performance**: Consider adding camera data to reduce roundtrips
|
|
186
|
-
|
|
187
|
-
## Conclusion
|
|
188
|
-
|
|
189
|
-
The cameras table implementation is **COMPLETE and FULLY FUNCTIONAL**. The database schema, migrations, DAOs, and interfaces are all properly implemented following the project's architectural patterns. The system supports:
|
|
190
|
-
|
|
191
|
-
- ✅ Camera management with geographic coordinates
|
|
192
|
-
- ✅ Many-to-one relationships between cameras and folders/videos
|
|
193
|
-
- ✅ UUID-based external references
|
|
194
|
-
- ✅ Geospatial queries for location-based camera searches
|
|
195
|
-
- ✅ Proper foreign key constraints with appropriate cascade behavior
|
|
196
|
-
- ✅ Full TypeScript type safety
|
|
197
|
-
- ✅ Performance optimization through proper indexing
|
|
198
|
-
|
|
199
|
-
**No database changes are required** - the system is ready for camera-based video processing workflows.
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# Folder Table CameraId Analysis
|
|
2
|
-
|
|
3
|
-
## Issue Summary
|
|
4
|
-
|
|
5
|
-
The `cameraId` column in the `folders` table is being saved as `null` despite being defined as optional in the schema and interface.
|
|
6
|
-
|
|
7
|
-
## Database Schema Analysis
|
|
8
|
-
|
|
9
|
-
### Current Schema (from migrations)
|
|
10
|
-
|
|
11
|
-
#### Initial Folder Table Creation (20250717161310_migration.ts)
|
|
12
|
-
|
|
13
|
-
```sql
|
|
14
|
-
CREATE TABLE folders (
|
|
15
|
-
id SERIAL PRIMARY KEY,
|
|
16
|
-
name VARCHAR NOT NULL,
|
|
17
|
-
createdBy INTEGER NOT NULL REFERENCES user(id) ON DELETE CASCADE,
|
|
18
|
-
status ENUM('UPLOADING', 'COMPLETE') NOT NULL DEFAULT 'UPLOADING',
|
|
19
|
-
studyId INTEGER NOT NULL REFERENCES study(id) ON DELETE CASCADE,
|
|
20
|
-
created_at TIMESTAMP,
|
|
21
|
-
updated_at TIMESTAMP
|
|
22
|
-
);
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
#### Camera Integration (20250911000000_migration.ts)
|
|
26
|
-
|
|
27
|
-
```sql
|
|
28
|
-
-- Added cameraId column to folders table
|
|
29
|
-
ALTER TABLE folders ADD COLUMN cameraId INTEGER NULLABLE
|
|
30
|
-
REFERENCES cameras(id) ON DELETE SET NULL;
|
|
31
|
-
CREATE INDEX ON folders (cameraId);
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Current Interface Definition
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
export interface IFolder {
|
|
38
|
-
id: number;
|
|
39
|
-
uuid: string;
|
|
40
|
-
name: string;
|
|
41
|
-
createdBy: number; // user.id
|
|
42
|
-
status: "UPLOADING" | "COMPLETE";
|
|
43
|
-
studyId: number; // study.id
|
|
44
|
-
cameraId?: number; // camera.id - OPTIONAL field
|
|
45
|
-
created_at: string;
|
|
46
|
-
updated_at: string;
|
|
47
|
-
study?: IStudy;
|
|
48
|
-
camera?: ICamera;
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## DAO Implementation Analysis
|
|
53
|
-
|
|
54
|
-
### Current FolderDAO Issues
|
|
55
|
-
|
|
56
|
-
1. **No Camera Relationship Joins**: The DAO queries join with `study` table but don't include `camera` joins
|
|
57
|
-
2. **Missing Camera Data Population**: Queries don't populate the optional `camera` field
|
|
58
|
-
3. **Basic CRUD Operations**: The `create()` method simply inserts the provided data without validation
|
|
59
|
-
|
|
60
|
-
### Key Methods Analysis
|
|
61
|
-
|
|
62
|
-
#### Create Method
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
async create(item: IFolder): Promise<IFolder> {
|
|
66
|
-
const [createdFolder] = await this._knex("folders")
|
|
67
|
-
.insert(item)
|
|
68
|
-
.returning("*");
|
|
69
|
-
return createdFolder;
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
- **Issue**: This will insert whatever `cameraId` is provided in the `item` parameter
|
|
74
|
-
- **Behavior**: If `cameraId` is undefined or not provided, it will be stored as `NULL` (which is valid)
|
|
75
|
-
|
|
76
|
-
#### Query Methods (getById, getByUuid, getAll)
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
// Current pattern - only joins with study
|
|
80
|
-
const folder = await this._knex("folders as f")
|
|
81
|
-
.innerJoin("study as s", "f.studyId", "s.id")
|
|
82
|
-
.select("f.*", this._knex.raw("to_jsonb(s.*) as study"))
|
|
83
|
-
.where("f.id", id)
|
|
84
|
-
.first();
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
- **Missing**: No LEFT JOIN with cameras table to populate camera data
|
|
88
|
-
- **Impact**: Even if `cameraId` has a valid value, the `camera` object won't be populated
|
|
89
|
-
|
|
90
|
-
## Root Cause Analysis
|
|
91
|
-
|
|
92
|
-
### Why CameraId is Null
|
|
93
|
-
|
|
94
|
-
1. **Optional Field Behavior**: Since `cameraId` is optional (`cameraId?: number`), if not explicitly provided in create requests, it defaults to `null`
|
|
95
|
-
|
|
96
|
-
2. **No Default Value**: Unlike other fields, there's no database-level default value for `cameraId`
|
|
97
|
-
|
|
98
|
-
3. **Application Logic Gap**: No validation or business logic to ensure `cameraId` is populated when appropriate
|
|
99
|
-
|
|
100
|
-
### Database Schema is Correct
|
|
101
|
-
|
|
102
|
-
The database schema properly supports `cameraId`:
|
|
103
|
-
|
|
104
|
-
- ✅ Column exists and is nullable
|
|
105
|
-
- ✅ Foreign key constraint to `cameras(id)`
|
|
106
|
-
- ✅ Proper ON DELETE SET NULL behavior
|
|
107
|
-
- ✅ Index created for performance
|
|
108
|
-
|
|
109
|
-
## Recommended Solutions
|
|
110
|
-
|
|
111
|
-
### 1. Immediate Fix: Verify Input Data
|
|
112
|
-
|
|
113
|
-
Check what data is being passed to the `create()` method:
|
|
114
|
-
|
|
115
|
-
- Log the `item` parameter in FolderDAO.create()
|
|
116
|
-
- Verify if `cameraId` is being provided in the request
|
|
117
|
-
|
|
118
|
-
### 2. Enhanced DAO Queries
|
|
119
|
-
|
|
120
|
-
Update FolderDAO to include camera relationships:
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// Enhanced getById with camera join
|
|
124
|
-
async getById(id: number): Promise<IFolder | null> {
|
|
125
|
-
const folder = await this._knex("folders as f")
|
|
126
|
-
.innerJoin("study as s", "f.studyId", "s.id")
|
|
127
|
-
.leftJoin("cameras as c", "f.cameraId", "c.id")
|
|
128
|
-
.select(
|
|
129
|
-
"f.*",
|
|
130
|
-
this._knex.raw("to_jsonb(s.*) as study"),
|
|
131
|
-
this._knex.raw("to_jsonb(c.*) as camera")
|
|
132
|
-
)
|
|
133
|
-
.where("f.id", id)
|
|
134
|
-
.first();
|
|
135
|
-
return folder || null;
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 3. API Layer Investigation
|
|
140
|
-
|
|
141
|
-
Check the API endpoints that create folders:
|
|
142
|
-
|
|
143
|
-
- Verify if `cameraId` is being extracted from request body
|
|
144
|
-
- Ensure DTO/validation layer passes `cameraId` through
|
|
145
|
-
- Check if frontend is sending `cameraId` in requests
|
|
146
|
-
|
|
147
|
-
### 4. Business Logic Validation
|
|
148
|
-
|
|
149
|
-
Consider if folders should always have a camera:
|
|
150
|
-
|
|
151
|
-
- If required: Add validation in create method
|
|
152
|
-
- If optional: Current behavior is correct (null is valid)
|
|
153
|
-
|
|
154
|
-
## Implementation Priority
|
|
155
|
-
|
|
156
|
-
1. **High**: Investigate API request data flow
|
|
157
|
-
2. **High**: Add camera relationship to DAO queries
|
|
158
|
-
3. **Medium**: Add logging to track cameraId values
|
|
159
|
-
4. **Low**: Consider business logic changes
|
|
160
|
-
|
|
161
|
-
## Files to Examine Next
|
|
162
|
-
|
|
163
|
-
1. `api-rel/src/controllers/folder/folder.controller.ts` - Controller logic
|
|
164
|
-
2. `api-rel/src/routes/folder/` - Route definitions and DTOs
|
|
165
|
-
3. Frontend folder creation forms - Check if cameraId is being sent
|
|
166
|
-
|
|
167
|
-
The database schema and DAO patterns are correctly implemented. The issue likely lies in the data flow from the API/frontend layers not providing `cameraId` values during folder creation.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { Knex } from "knex";
|
|
2
|
-
|
|
3
|
-
export async function up(knex: Knex): Promise<void> {
|
|
4
|
-
await knex.schema.alterTable("cameras", (table) => {
|
|
5
|
-
// Add index for case-insensitive name searches
|
|
6
|
-
table.index(knex.raw("LOWER(name)"), "idx_cameras_name_lower");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
// Add GIN index for full-text search if needed for fuzzy matching
|
|
10
|
-
await knex.raw(`
|
|
11
|
-
CREATE INDEX idx_cameras_name_gin
|
|
12
|
-
ON cameras
|
|
13
|
-
USING GIN (to_tsvector('english', name))
|
|
14
|
-
`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function down(knex: Knex): Promise<void> {
|
|
18
|
-
await knex.raw("DROP INDEX IF EXISTS idx_cameras_name_gin");
|
|
19
|
-
await knex.schema.alterTable("cameras", (table) => {
|
|
20
|
-
table.dropIndex(knex.raw("LOWER(name)"), "idx_cameras_name_lower");
|
|
21
|
-
});
|
|
22
|
-
}
|