| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- import { Db, ObjectId, WithId } from 'mongodb';
- import { FFBProduction } from 'src/FFB/ffb-production.schema';
- export class FFBProductionRepository {
- private readonly collectionName = 'FFB Production';
- constructor(private readonly db: Db) { }
- private get collection() {
- return this.db.collection<FFBProduction & { vector?: number[] }>(this.collectionName);
- }
- async init() {
- const collections = await this.db.listCollections({ name: this.collectionName }).toArray();
- if (collections.length === 0) {
- await this.db.createCollection(this.collectionName);
- console.log(`✅ Created collection: ${this.collectionName}`);
- }
- }
- async create(ffb: FFBProduction & { vector?: number[] }): Promise<FFBProduction & { vector?: number[] }> {
- const result = await this.collection.insertOne({
- ...ffb,
- productionDate: new Date(ffb.productionDate),
- vector: ffb.vector, // optional vector
- });
- return { ...ffb, _id: result.insertedId.toString() };
- }
- async findAll(filter: Record<string, any> = {}, options: { page?: number, limit?: number } = {}): Promise<{ data: (FFBProduction & { vector?: number[] })[], total: number }> {
- const { page = 1, limit = 10 } = options;
- const skip = (page - 1) * limit;
- const [results, total] = await Promise.all([
- this.collection.find(filter).skip(skip).limit(limit).toArray(),
- this.collection.countDocuments(filter)
- ]);
- const data = results.map((r: WithId<FFBProduction & { vector?: number[] }>) => ({
- ...r,
- _id: r._id?.toString(),
- }));
- return { data, total };
- }
- async findById(id: string): Promise<(FFBProduction & { vector?: number[] }) | null> {
- const result = await this.collection.findOne({ _id: new ObjectId(id) as any });
- return result ? { ...result, _id: result._id.toString() } : null;
- }
- async delete(id: string) {
- return this.collection.deleteOne({ _id: new ObjectId(id) as any });
- }
- async deleteMany(filter: Record<string, any>) {
- return this.collection.deleteMany(filter);
- }
- async update(id: string, update: Partial<FFBProduction>): Promise<void> {
- await this.collection.updateOne(
- { _id: new ObjectId(id) as any },
- { $set: update }
- );
- }
- async findOne(filter: Record<string, any> = {}): Promise<FFBProduction | null> {
- const result = await this.collection.findOne(filter);
- return result ? { ...result, _id: result._id.toString() } : null;
- }
- async distinct(field: string, filter: Record<string, any> = {}): Promise<any[]> {
- return this.collection.distinct(field, filter);
- }
- /** Optional: helper for vector search via aggregation */
- async vectorSearch(vector: number[], k = 5, numCandidates = 50, filter: Record<string, any> = {}) {
- return this.collection
- .aggregate([
- {
- $vectorSearch: {
- index: 'vector_index',
- queryVector: vector,
- path: 'vector',
- numCandidates,
- limit: k,
- filter // Add filter here
- }
- },
- {
- $project: {
- _id: 1,
- productionDate: 1,
- site: 1,
- phase: 1,
- block: 1,
- quantity: 1,
- quantityUom: 1,
- weight: 1,
- weightUom: 1,
- remarks: 1,
- score: { "$meta": "vectorSearchScore" } // correctly get the score
- }
- }
- ])
- .toArray();
- }
- async aggregate(pipeline: Array<Record<string, any>>): Promise<any[]> {
- // Optional: log the pipeline for debugging
- // console.log('Executing aggregation pipeline:', JSON.stringify(pipeline, null, 2));
- const pipelineWithDates = pipeline.map(stage => {
- if ('$match' in stage && 'productionDate' in stage.$match) {
- const pd = stage.$match.productionDate;
- if (pd.$gte) pd.$gte = new Date(pd.$gte);
- if (pd.$lte) pd.$lte = new Date(pd.$lte);
- }
- return stage;
- });
- // Execute aggregation
- const results = await this.collection.aggregate(pipelineWithDates).toArray();
- // console.log('Aggregation results:', results);
- // Optional: strip out any internal vector fields if accidentally included
- return results.map(r => {
- const { vector, ...rest } = r;
- return rest;
- });
- }
- }
|