flexmonster-mongo-connector
Version:
Custom data source API implementation for MongoDB
230 lines (184 loc) • 8.84 kB
text/typescript
import {FilterQueryBuilder} from './FilterQueryBuilder';
import {ProjectionQueryBuilder} from './ProjectionQueryBuilder';
import {GroupingQueryBuilder} from './GroupingQueryBuilder';
import { MongoPipelineStages } from '../../utils/consts/MongoPipelineStages';
import { APISchema } from '../../schema/APISchema';
import { IQuery } from '../IQuery';
export class QueryBuilder {
private static _queryBuilderInstance: QueryBuilder = null;
private _filterQueryBuilder: FilterQueryBuilder = null;
private _projectionQueryBuilder: ProjectionQueryBuilder = null;
private _groupingQueryBuilder: GroupingQueryBuilder = null;
constructor() {
if (QueryBuilder._queryBuilderInstance != null) throw new Error("Initialization failed: "+
"use Singleton.getInstance() instead of new.");
this._filterQueryBuilder = new FilterQueryBuilder();
this._projectionQueryBuilder = new ProjectionQueryBuilder();
this._groupingQueryBuilder = new GroupingQueryBuilder();
QueryBuilder._queryBuilderInstance = this;
}
public static getInstance() {
if (this._queryBuilderInstance == null) {
this._queryBuilderInstance = new QueryBuilder();
}
return this._queryBuilderInstance;
}
public buildDrillThroughPipeline(drillThroughQuery: any, schema: APISchema, clientSideLimit: number) {
if (drillThroughQuery == null) throw new Error("Illegal argument exception. Query cannot be null");
const pipeline: any[] = [];
const extendedQuery: any = {
"aggs": {
"by": {
"rows": drillThroughQuery["fields"]
}
},
"filter": drillThroughQuery["filter"]
};
if (extendedQuery["filter"] != null) {
pipeline.push({
[MongoPipelineStages.MATCH]: this._filterQueryBuilder.buildFilterQuery(extendedQuery["filter"], schema)
});
}
delete extendedQuery["filter"];
pipeline.push({
[MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(extendedQuery, schema)
});
pipeline.push({
[MongoPipelineStages.LIMIT]: clientSideLimit
});
return pipeline;
}
// public buildAggregationPipeline(query: any, schema: APISchema) {
// if (query == null) throw new Error("Illegal argument exception. Query cannot be null");
// const pipeline: any[] = [];
// pipeline.push({
// [MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(query, schema)
// });
// if (query["filter"] != null) {
// pipeline.push({
// "$match": this._filterQueryBuilder.buildFilterQuery(query["filter"], schema)
// });
// }
// const queryCopy: any = JSON.parse(JSON.stringify(query));
// delete queryCopy["filter"]; //query with no filter;
// pipeline.push({
// [MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(queryCopy, schema)
// });
// if (query["aggs"] != null) {
// pipeline.push(this._groupingQueryBuilder.buildGroupStage(query["aggs"]));
// }
// return pipeline;
// }
public buildFlatPipelineFacet(query: any | IQuery[], schema: APISchema) {
if (query == null) throw new Error("Illegal argument exception. Query cannot be null");
const pipeline: any[] = [];
const grandTotalQuery: IQuery = query.length === 1 ? null : query[0];
const dataRecords: IQuery = query.length === 1 ? query[0] : query[1];
const extendedQuery: any = {
"aggs": {
"by": {
"rows": dataRecords.clientQuery["fields"]
}
},
"filter": dataRecords.clientQuery["filter"]
};
if (extendedQuery["filter"] != null) {
pipeline.push({
"$match": this._filterQueryBuilder.buildFilterQuery(extendedQuery["filter"], schema)
});
//need to test performance with and without this block
// const queryCopy: any = JSON.parse(JSON.stringify(extendedQuery));
// delete queryCopy["filter"]; //query with no filter;
// pipeline.push({
// [MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(queryCopy, schema)
// });
}
delete extendedQuery["filter"]; //query with no filter;
pipeline.push({
[MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(extendedQuery, schema)
});
const facetStage: any = {};
if (grandTotalQuery !== null) facetStage[grandTotalQuery.definition] = [this._groupingQueryBuilder.buildGroupStage(grandTotalQuery.clientQuery["aggs"])];
facetStage[dataRecords.definition] = [pipeline[0]];
pipeline.push({
[MongoPipelineStages.FACET]: facetStage
});
//console.log(">>>>>pipe", JSON.stringify(pipeline))
return pipeline;
}
public buildAggregationPipelineFacet(queries: any | IQuery[], schema: APISchema, templateQuery?: IQuery, isPaginated?: boolean) {
if (queries == null) throw new Error("Illegal argument exception. Query cannot be null");
const pipeline: any[] = [];
const intersectionQuery: IQuery = templateQuery === undefined ? (<IQuery[]>queries).shift() : JSON.parse(JSON.stringify(templateQuery));
if (intersectionQuery.clientQuery["filter"] != null) {
pipeline.push({
[MongoPipelineStages.MATCH]: this._filterQueryBuilder.buildFilterQuery(intersectionQuery.clientQuery["filter"], schema)
});
delete intersectionQuery.clientQuery["filter"]
}
pipeline.push({
[MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(intersectionQuery.clientQuery, schema)
});
if (intersectionQuery.clientQuery["aggs"] != null) {
const facetStage: any = {};
for (let i = 0; i < queries.length; i++) {
const query: IQuery = queries[i];
const facet: any[] = [this._groupingQueryBuilder.buildGroupStage(query.clientQuery["aggs"])];
if (isPaginated !== undefined && isPaginated
&& (query.queryStats.chunkToLoad < query.queryStats.expectedNumberOfRecords)) {
this.applyPaging(facet, {
skipNumber: query.queryStats.sumOfLoadedRecords,
limitNumber: query.queryStats.chunkToLoad
});
}
//console.log(">>>>>Query", JSON.stringify(facet, null, ""));
facetStage[queries[i].definition] = facet;
}
pipeline.push({
[MongoPipelineStages.FACET]: facetStage
});
}
//console.log(">>>>>>>MongoQuery", JSON.stringify(pipeline, null, ''));
return pipeline;
}
public buildMembersPipeline(fieldObject: any, schema: APISchema): any[] {
let query: any = {
"aggs": {
"by": {
"rows": [fieldObject.field]
}
}
};
let pipeline: any[] = [];
// pipeline.push({
// [MongoPipelineStages.SORT]: {
// [field.uniqueName]: 1
// }
// });
if (fieldObject["filter"] !== undefined) {
query["filter"] = fieldObject["filter"];
pipeline.push({
[MongoPipelineStages.MATCH]: this._filterQueryBuilder.buildFilterQuery(query["filter"], schema)
});
}
pipeline.push({
[MongoPipelineStages.PROJECT]: this._projectionQueryBuilder.buildProjectionStage(query, schema)
});
pipeline.push(this._groupingQueryBuilder.buildGroupStage(query["aggs"]));
return pipeline;
}
private applyPaging(pipeline: any[], pagingObject?: PagingObject): void {
if (pagingObject != null) {
pipeline.push({
[MongoPipelineStages.SKIP]: pagingObject.skipNumber
});
pipeline.push({
[MongoPipelineStages.LIMIT]: pagingObject.limitNumber
});
}
}
}
export interface PagingObject {
skipNumber: number;
limitNumber: number;
}