From bacf05da9cf8cc188d6734df52dfe7516a6d1dd3 Mon Sep 17 00:00:00 2001 From: Alexey Velikiy Date: Mon, 6 Aug 2018 23:21:58 +0300 Subject: [PATCH] db-many querys & usage in segments --- server/.vscode/launch.json | 3 +- server/src/models/analytic_unit_model.ts | 7 +-- server/src/models/segment_model.ts | 31 +++++++--- server/src/routes/analytic_units_router.ts | 19 +++---- server/src/routes/segments_router.ts | 30 +++------- server/src/services/data_service.ts | 66 ++++++++++++++++++---- 6 files changed, 97 insertions(+), 59 deletions(-) diff --git a/server/.vscode/launch.json b/server/.vscode/launch.json index 47a65b1..94af8a5 100644 --- a/server/.vscode/launch.json +++ b/server/.vscode/launch.json @@ -17,7 +17,8 @@ //"outFiles": [ "/home/alex/Projects/hastic-server/server.js" ], "port": 9229, "restart": true, - "trace": true + "trace": true, + "timeout": 100000 } ] } \ No newline at end of file diff --git a/server/src/models/analytic_unit_model.ts b/server/src/models/analytic_unit_model.ts index 8203625..73b5d9f 100644 --- a/server/src/models/analytic_unit_model.ts +++ b/server/src/models/analytic_unit_model.ts @@ -61,22 +61,21 @@ export class AnalyticUnit { ); } - } export async function findById(id: AnalyticUnitId): Promise { - return AnalyticUnit.fromObject(db.findOne(id)); + return AnalyticUnit.fromObject(await db.findOne(id)); } /** * Creates and updates new unit.id - * + * * @param unit to create * @returns unit.id */ export async function create(unit: AnalyticUnit): Promise { - return unit.id = await db.insertOne(unit); + return unit.id = await db.insertOne(unit.toObject()); } export async function remove(id: AnalyticUnitId): Promise { diff --git a/server/src/models/segment_model.ts b/server/src/models/segment_model.ts index b65ee88..be91f16 100644 --- a/server/src/models/segment_model.ts +++ b/server/src/models/segment_model.ts @@ -9,11 +9,15 @@ type SegmentId = string; export class Segment { constructor( + public auId: AnalyticUnitId, public from: number, public to: number, public labeled: boolean, public id?: SegmentId ) { + if(auId === undefined) { + throw new Error('AnalyticUnitId is undefined'); + } if(from === undefined) { throw new Error('from is undefined'); } @@ -28,6 +32,7 @@ export class Segment { public toObject() { return { _id: this.id, + auId: this.auId, from: this.from, to: this.to, labeled: this.labeled @@ -39,24 +44,34 @@ export class Segment { throw new Error('obj is undefined'); } return new Segment( - obj.from, obj.to, + obj.auId, +obj.from, +obj.to, obj.labeled, obj.id || obj._id ); } } - -export function getLabeledSegments(id: AnalyticUnitId) { - //return db. +export type FindManyQuery = { + timeFromGTE?: number, + timeToLTE?: number, + intexGT?: number } -export function getPredicted(id: AnalyticUnitId) { - +export async function findMany(id: AnalyticUnitId, query: FindManyQuery): Promise { + var dbQuery: any = { auId: id }; + if(query.timeFromGTE !== undefined) { + dbQuery.from = { $gte: query.timeFromGTE }; + } + if(query.timeToLTE !== undefined) { + dbQuery.to = { $lte: query.timeToLTE }; + } + let segs = await db.findMany(dbQuery); + return segs.map(Segment.fromObject); } -export async function insertSegments(id: any, segments: Segment[]) { +export async function insertSegments(id: AnalyticUnitId, segments: Segment[]) { + return db.insertMany(segments.map(s => s.toObject())); } export function removeSegments(idsToRemove: SegmentId[]) { - + return db.removeMany(idsToRemove); } diff --git a/server/src/routes/analytic_units_router.ts b/server/src/routes/analytic_units_router.ts index 5f06072..763ddaa 100644 --- a/server/src/routes/analytic_units_router.ts +++ b/server/src/routes/analytic_units_router.ts @@ -25,7 +25,7 @@ async function sendStatus(ctx: Router.IRouterContext) { } -async function findItem(ctx: Router.IRouterContext) { +async function getUnit(ctx: Router.IRouterContext) { try { let id = ctx.request.query.id; @@ -49,7 +49,7 @@ async function findItem(ctx: Router.IRouterContext) { } } -async function createItem(ctx: Router.IRouterContext) { +async function createUnit(ctx: Router.IRouterContext) { try { let newId = await createAnalyticUnitFromObject(ctx.request.body); ctx.response.body = { id: newId }; @@ -62,14 +62,9 @@ async function createItem(ctx: Router.IRouterContext) { } } -function deleteItem(ctx: Router.IRouterContext) { +async function deleteUnit(ctx: Router.IRouterContext) { try { - let id = ctx.request.query.id; - - if(id !== undefined) { - AnalyticUnit.remove(id); - } - + await AnalyticUnit.remove(ctx.request.query.id); ctx.response.body = { code: 200, message: 'Success' @@ -86,7 +81,7 @@ function deleteItem(ctx: Router.IRouterContext) { export var router = new Router(); +router.get('/', getUnit); router.get('/status', sendStatus); -router.get('/', findItem); -router.post('/', createItem); -router.delete('/', deleteItem); +router.post('/', createUnit); +router.delete('/', deleteUnit); diff --git a/server/src/routes/segments_router.ts b/server/src/routes/segments_router.ts index 80dcc80..3f9f37a 100644 --- a/server/src/routes/segments_router.ts +++ b/server/src/routes/segments_router.ts @@ -3,35 +3,21 @@ import * as Router from 'koa-router'; import { AnalyticUnitId } from '../models/analytic_unit_model'; import { - getLabeledSegments, + findMany, insertSegments, removeSegments, } from '../models/segment_model'; import { runLearning } from '../controllers/analytics_controller'; -async function sendSegments(ctx: Router.IRouterContext) { +async function getSegments(ctx: Router.IRouterContext) { let id: AnalyticUnitId = ctx.request.query.id; - let lastSegmentId = ctx.request.query.lastSegmentId; - let timeFrom = ctx.request.query.from; - let timeTo = ctx.request.query.to; - - let segments = await getLabeledSegments(id); - - // // Id filtering - // if(lastSegmentId !== undefined) { - // segments = segments.filter(el => el.id > lastSegmentId); - // } - - // // Time filtering - // if(timeFrom !== undefined) { - // segments = segments.filter(el => el.finish > timeFrom); - // } - - // if(timeTo !== undefined) { - // segments = segments.filter(el => el.start < timeTo); - // } + let segments = await findMany(id, { + intexGT: ctx.request.query.lastSegmentId, + timeFromGTE: ctx.request.query.from, + timeToLTE: ctx.request.query.to + }); ctx.response.body = { segments } @@ -56,5 +42,5 @@ async function updateSegments(ctx: Router.IRouterContext) { export const router = new Router(); -router.get('/', sendSegments); +router.get('/', getSegments); router.patch('/', updateSegments); diff --git a/server/src/services/data_service.ts b/server/src/services/data_service.ts index ae0ee09..90cff7a 100644 --- a/server/src/services/data_service.ts +++ b/server/src/services/data_service.ts @@ -9,37 +9,48 @@ export enum Collection { ANALYTIC_UNITS, SEGMENTS }; /** * Class which helps to make queries to your collection - * + * * @param { string | object } query: a key as a string or mongodb-style query */ export type DBQ = { + findOne: (query: string | object) => any, + findMany: (query: string[] | object) => any[], insertOne: (document: object) => string, insertMany: (documents: object[]) => string[], updateOne: (query: string | object, updateQuery: any) => void, - findOne: (query: string | object) => any, - removeOne: (query: string | object) => number + removeOne: (query: string) => boolean + removeMany: (query: string[] | object) => number } export function makeDBQ(collection: Collection): DBQ { return { - insertOne: dbInsert.bind(null, collection), - insertMany: dbInsertMany.bind(null, collection), - updateOne: dbUpdate.bind(null, collection), findOne: dbFindOne.bind(null, collection), - removeOne: dbRemove.bind(null, collection) + findMany: dbFindMany.bind(null, collection), + insertOne: dbInsertOne.bind(null, collection), + insertMany: dbInsertMany.bind(null, collection), + updateOne: dbUpdateOne.bind(null, collection), + removeOne: dbRemoveOne.bind(null, collection), + removeMany: dbRemoveMany.bind(null, collection) } } -function wrapIdToQuery(query: string | object) { +function wrapIdToQuery(query: string | object): any { if(typeof query === 'string') { return { _id: query }; } return query; } +function wrapIdsToQuery(query: string[] | object): any { + if(Array.isArray(query)) { + return { _id: { $in: query } }; + } + return query; +} + const db = new Map(); -let dbInsert = (collection: Collection, doc: object) => { +let dbInsertOne = (collection: Collection, doc: object) => { return new Promise((resolve, reject) => { db[collection].insert(doc, (err, newDoc) => { if(err) { @@ -63,7 +74,7 @@ let dbInsertMany = (collection: Collection, docs: object[]) => { }); } -let dbUpdate = (collection: Collection, query: string | object, updateQuery: object) => { +let dbUpdateOne = (collection: Collection, query: string | object, updateQuery: object) => { query = wrapIdToQuery(query); return new Promise((resolve, reject) => { db[collection].update(query, updateQuery, { /* options */ }, (err: Error) => { @@ -89,8 +100,38 @@ let dbFindOne = (collection: Collection, query: string | object) => { }); } -let dbRemove = (collection: Collection, query: string | object) => { - query = wrapIdToQuery(query); +let dbFindMany = (collection: Collection, query: string[] | object) => { + query = wrapIdsToQuery(query); + return new Promise((resolve, reject) => { + db[collection].findOne(query, (err, docs) => { + if(err) { + reject(err); + } else { + resolve(docs); + } + }); + }); +} + +let dbRemoveOne = (collection: Collection, id: string) => { + let query = { _id: id }; + return new Promise((resolve, reject) => { + db[collection].remove(query, (err, numRemoved) => { + if(err) { + reject(err); + } else { + if(numRemoved > 1) { + throw new Error(`Removed ${numRemoved} elements with id: ${id}. Only one is Ok.`); + } else { + resolve(numRemoved == 1); + } + } + }); + }); +} + +let dbRemoveMany = (collection: Collection, query: string[] | object) => { + query = wrapIdsToQuery(query); return new Promise((resolve, reject) => { db[collection].remove(query, (err, numRemoved) => { if(err) { @@ -102,6 +143,7 @@ let dbRemove = (collection: Collection, query: string | object) => { }); } + function maybeCreateDir(path: string): void { if(fs.existsSync(path)) { return;