Browse Source

Anti-segments #142 (#150)

Node.js part of #142

- Merge segments while inserting
- Add deleted flag to segments
pull/1/head
rozetko 6 years ago committed by GitHub
parent
commit
504283d918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      server/src/controllers/analytics_controller.ts
  2. 37
      server/src/models/segment_model.ts
  3. 46
      server/src/services/data_service.ts

6
server/src/controllers/analytics_controller.ts

@ -210,7 +210,7 @@ function processPredictionResult(analyticUnitId: AnalyticUnit.AnalyticUnitId, ta
); );
} }
let segments = payload.segments.map(segment => new Segment.Segment(analyticUnitId, segment.from, segment.to, false)); let segments = payload.segments.map(segment => new Segment.Segment(analyticUnitId, segment.from, segment.to, false, false));
return { return {
lastPredictionTime: payload.lastPredictionTime, lastPredictionTime: payload.lastPredictionTime,
@ -240,8 +240,10 @@ export async function updateSegments(
) { ) {
let [addedIds, removed] = await Promise.all([ let [addedIds, removed] = await Promise.all([
Segment.insertSegments(segmentsToInsert), Segment.insertSegments(segmentsToInsert),
Segment.removeSegments(removedIds) Segment.setSegmentsDeleted(removedIds)
]); ]);
removed = removed.map(s => s._id);
// TODO: move setting status somehow "inside" learning // TODO: move setting status somehow "inside" learning
await AnalyticUnit.setStatus(id, AnalyticUnit.AnalyticUnitStatus.PENDING); await AnalyticUnit.setStatus(id, AnalyticUnit.AnalyticUnitStatus.PENDING);
runLearning(id).then(() => runPredict(id)); runLearning(id).then(() => runPredict(id));

37
server/src/models/segment_model.ts

@ -2,6 +2,8 @@ import { AnalyticUnitId } from './analytic_unit_model';
import { Collection, makeDBQ } from '../services/data_service'; import { Collection, makeDBQ } from '../services/data_service';
import * as _ from 'lodash';
let db = makeDBQ(Collection.SEGMENTS); let db = makeDBQ(Collection.SEGMENTS);
@ -13,6 +15,7 @@ export class Segment {
public from: number, public from: number,
public to: number, public to: number,
public labeled: boolean = false, public labeled: boolean = false,
public deleted: boolean = false,
public id?: SegmentId public id?: SegmentId
) { ) {
if(analyticUnitId === undefined) { if(analyticUnitId === undefined) {
@ -38,7 +41,8 @@ export class Segment {
analyticUnitId: this.analyticUnitId, analyticUnitId: this.analyticUnitId,
from: this.from, from: this.from,
to: this.to, to: this.to,
labeled: this.labeled labeled: this.labeled,
deleted: this.deleted
}; };
} }
@ -49,7 +53,7 @@ export class Segment {
return new Segment( return new Segment(
obj.analyticUnitId, obj.analyticUnitId,
+obj.from, +obj.to, +obj.from, +obj.to,
obj.labeled, obj._id obj.labeled, obj.deleted, obj._id
); );
} }
} }
@ -80,9 +84,38 @@ export async function findMany(id: AnalyticUnitId, query: FindManyQuery): Promis
} }
export async function insertSegments(segments: Segment[]) { export async function insertSegments(segments: Segment[]) {
let segmentIdsToRemove: SegmentId[] = [];
let segmentsToInsert: Segment[] = [];
for(let segment of segments) {
let intersectedSegments = await db.findMany({
analyticUnitId: segments[0].analyticUnitId,
to: { $gte: segment.from },
from: { $lte: segment.to },
labeled: segment.labeled,
deleted: segment.deleted
});
if(intersectedSegments.length > 0) {
let from = _.minBy(intersectedSegments, 'from').from;
let to = _.maxBy(intersectedSegments, 'to').to;
let newSegment = Segment.fromObject(segment.toObject());
newSegment.from = from;
newSegment.to = to;
segmentIdsToRemove = segmentIdsToRemove.concat(intersectedSegments.map(s => s._id));
segmentsToInsert.push(newSegment);
} else {
segmentsToInsert.push(segment);
}
}
await db.removeMany(segmentIdsToRemove);
return db.insertMany(segments.map(s => s.toObject())); return db.insertMany(segments.map(s => s.toObject()));
} }
export async function setSegmentsDeleted(ids: SegmentId[]) {
return db.updateMany(ids, { deleted: true });
}
export function removeSegments(idsToRemove: SegmentId[]) { export function removeSegments(idsToRemove: SegmentId[]) {
return db.removeMany(idsToRemove); return db.removeMany(idsToRemove);
} }

46
server/src/services/data_service.ts

@ -17,7 +17,8 @@ export type DBQ = {
findMany: (query: string[] | object) => Promise<any[]>, findMany: (query: string[] | object) => Promise<any[]>,
insertOne: (document: object) => Promise<string>, insertOne: (document: object) => Promise<string>,
insertMany: (documents: object[]) => Promise<string[]>, insertMany: (documents: object[]) => Promise<string[]>,
updateOne: (query: string | object, updateQuery: any) => Promise<void>, updateOne: (query: string | object, updateQuery: any) => Promise<any>,
updateMany: (query: string[] | object, updateQuery: any) => Promise<any[]>,
removeOne: (query: string) => Promise<boolean> removeOne: (query: string) => Promise<boolean>
removeMany: (query: string[] | object) => Promise<number> removeMany: (query: string[] | object) => Promise<number>
} }
@ -29,6 +30,7 @@ export function makeDBQ(collection: Collection): DBQ {
insertOne: dbInsertOne.bind(null, collection), insertOne: dbInsertOne.bind(null, collection),
insertMany: dbInsertMany.bind(null, collection), insertMany: dbInsertMany.bind(null, collection),
updateOne: dbUpdateOne.bind(null, collection), updateOne: dbUpdateOne.bind(null, collection),
updateMany: dbUpdateMany.bind(null, collection),
removeOne: dbRemoveOne.bind(null, collection), removeOne: dbRemoveOne.bind(null, collection),
removeMany: dbRemoveMany.bind(null, collection) removeMany: dbRemoveMany.bind(null, collection)
} }
@ -88,14 +90,42 @@ let dbUpdateOne = (collection: Collection, query: string | object, updateQuery:
// https://github.com/louischatriot/nedb#updating-documents // https://github.com/louischatriot/nedb#updating-documents
let nedbUpdateQuery = { $set: updateQuery } let nedbUpdateQuery = { $set: updateQuery }
query = wrapIdToQuery(query); query = wrapIdToQuery(query);
return new Promise<void>((resolve, reject) => { return new Promise<any>((resolve, reject) => {
db.get(collection).update(query, nedbUpdateQuery, { /* options */ }, (err: Error) => { db.get(collection).update(
if(err) { query,
reject(err); nedbUpdateQuery,
} else { { returnUpdatedDocs: true },
resolve(); (err: Error, numAffected: number, affectedDocument: any) => {
if(err) {
reject(err);
} else {
resolve(affectedDocument);
}
} }
}); );
});
}
let dbUpdateMany = (collection: Collection, query: string[] | object, updateQuery: object) => {
// https://github.com/louischatriot/nedb#updating-documents
if(isEmptyArray(query)) {
return Promise.resolve([]);
}
let nedbUpdateQuery = { $set: updateQuery };
query = wrapIdsToQuery(query);
return new Promise<any[]>((resolve, reject) => {
db.get(collection).update(
query,
nedbUpdateQuery,
{ returnUpdatedDocs: true, multi: true },
(err: Error, numAffected: number, affectedDocuments: any[]) => {
if(err) {
reject(err);
} else {
resolve(affectedDocuments);
}
}
);
}); });
} }

Loading…
Cancel
Save