From 4ceac325f940ad858d88b2448dbdfa3267885b14 Mon Sep 17 00:00:00 2001 From: Robin Reyer Date: Tue, 23 Apr 2024 16:12:16 +0200 Subject: [PATCH 1/2] fix order of pagination and search --- src/mongodbGenerator.ts | 292 ++++++++++++++++++++++------------------ 1 file changed, 159 insertions(+), 133 deletions(-) diff --git a/src/mongodbGenerator.ts b/src/mongodbGenerator.ts index 999cdd9..a6dd766 100644 --- a/src/mongodbGenerator.ts +++ b/src/mongodbGenerator.ts @@ -1,24 +1,24 @@ -import url from 'url'; +import url from "url"; -import { generateMatchFromFilterExpr } from './filterGenerator'; -import { generateLimitFromTopExpr } from './limitGenerator'; -import { generateSkipFromSkipExpr } from './skipGenerator'; -import { generateSortFromOrderbyExpr } from './sortGenerator'; -import { generateProjectFromSelectExpr } from './selectGenerator'; -import { generateLookupFromExpand, CollectionMap } from './lookupGenerator'; -import { generateComputeStageFromComputedExpr } from './computeGenerator'; -import { generateSearchFromSearchExpr } from './searchGenerator'; +import { generateMatchFromFilterExpr } from "./filterGenerator"; +import { generateLimitFromTopExpr } from "./limitGenerator"; +import { generateSkipFromSkipExpr } from "./skipGenerator"; +import { generateSortFromOrderbyExpr } from "./sortGenerator"; +import { generateProjectFromSelectExpr } from "./selectGenerator"; +import { generateLookupFromExpand, CollectionMap } from "./lookupGenerator"; +import { generateComputeStageFromComputedExpr } from "./computeGenerator"; +import { generateSearchFromSearchExpr } from "./searchGenerator"; -import { oDataParameters } from 'odatafy-parser'; -import { Document } from 'mongodb'; +import { oDataParameters } from "odatafy-parser"; +import { Document } from "mongodb"; export type MongoDBODatafyOpts = { - expandMapping?: CollectionMap, - returnEmptyPipeline?: boolean, - regexSearchFields?: string[], - returnDataCountQuery?: boolean, - returnCountOnly?: boolean -} + expandMapping?: CollectionMap; + returnEmptyPipeline?: boolean; + regexSearchFields?: string[]; + returnDataCountQuery?: boolean; + returnCountOnly?: boolean; +}; /** * Get MongoDB aggregation query from a given url can be obtained by nodes req.url @@ -26,25 +26,41 @@ export type MongoDBODatafyOpts = { * @param opts options for getting the url * @returns MongoDB aggregation query */ -export function getQueryFromUrl(oDataUrl: string, opts?: MongoDBODatafyOpts): Document[] { - const query = url.parse(oDataUrl, true).query; - const validParams = ['filter', 'orderby', 'skip', 'top', 'expand', 'compute', 'select', 'search']; - const params = Object.keys(query); - - let parseParameters: oDataParameters = {} - - validParams.forEach((param: string) => { - //check if url - if (params.includes(param) && params.includes('$' + param)) { - throw new Error(`Malformed oData url, cannot contain param: ${param} and param: $${param}`) - } - - if (params.includes(param) || params.includes('$' + param)) { - parseParameters[param as keyof oDataParameters] = query[(params.includes(param) ? param : '$' + param)] as string - } - }); - - return getQuery(parseParameters, opts); +export function getQueryFromUrl( + oDataUrl: string, + opts?: MongoDBODatafyOpts +): Document[] { + const query = url.parse(oDataUrl, true).query; + const validParams = [ + "filter", + "orderby", + "skip", + "top", + "expand", + "compute", + "select", + "search", + ]; + const params = Object.keys(query); + + let parseParameters: oDataParameters = {}; + + validParams.forEach((param: string) => { + //check if url + if (params.includes(param) && params.includes("$" + param)) { + throw new Error( + `Malformed oData url, cannot contain param: ${param} and param: $${param}` + ); + } + + if (params.includes(param) || params.includes("$" + param)) { + parseParameters[param as keyof oDataParameters] = query[ + params.includes(param) ? param : "$" + param + ] as string; + } + }); + + return getQuery(parseParameters, opts); } /** @@ -53,100 +69,110 @@ export function getQueryFromUrl(oDataUrl: string, opts?: MongoDBODatafyOpts): Do * @param opts options for getting the url * @returns MongoDB aggregaion pipeline */ -export function getQuery(parameters: oDataParameters, opts?: MongoDBODatafyOpts): Document[] { - const pipeline: Document[] = []; - let countPipeline: Document[] = []; - - if (parameters.expand) { - pipeline.push(...generateLookupFromExpand(parameters.expand, opts?.expandMapping? opts.expandMapping: {})); - } - - if (parameters.compute) { - pipeline.push(generateComputeStageFromComputedExpr(parameters.compute)); - } - - if (parameters.filter) { - pipeline.push(generateMatchFromFilterExpr(parameters.filter)); - } - - /* copy to count query */ - if(opts?.returnDataCountQuery || opts?.returnCountOnly) { - countPipeline = [...pipeline]; - } - - - if (parameters.orderby) { - pipeline.push(generateSortFromOrderbyExpr(parameters.orderby)); - } - - if (parameters.skip) { - pipeline.push(generateSkipFromSkipExpr(parameters.skip)); - } - - if (parameters.top) { - pipeline.push(generateLimitFromTopExpr(parameters.top)); - } - - if(parameters.select) { - pipeline.push(generateProjectFromSelectExpr(parameters.select)); - } - - if(parameters.search) { - const searchExpr = generateSearchFromSearchExpr(parameters.search, opts?.regexSearchFields); - - pipeline.push(searchExpr); - countPipeline.push(searchExpr); - } - - //add default steps if pipline must not be empty - i.e. in mongoose an empty pipeline returns an error - if(!opts?.returnEmptyPipeline && pipeline.length == 0) { - pipeline.push( - { - $addFields: { - odatafyMongoDBTempField: "" - } - }, - { - $project: { - odatafyMongoDBTempField: 0 - } - } - ) - - countPipeline = [...pipeline]; - } - - countPipeline.push({ - $count: "count" - }); - - if(opts?.returnCountOnly) { - return countPipeline - } - - if(opts?.returnDataCountQuery) { - return [ - { - "$facet": { - "data": pipeline, - "countTmp": countPipeline - } - }, - { - "$addFields": { - "countTmp2": { - "$first": "$countTmp" - } - } - }, - { - "$project": { - "data": "$data", - "count": "$countTmp2.count" - } - } - ] - } - - return pipeline; -} \ No newline at end of file +export function getQuery( + parameters: oDataParameters, + opts?: MongoDBODatafyOpts +): Document[] { + const pipeline: Document[] = []; + let countPipeline: Document[] = []; + + if (parameters.expand) { + pipeline.push( + ...generateLookupFromExpand( + parameters.expand, + opts?.expandMapping ? opts.expandMapping : {} + ) + ); + } + + if (parameters.compute) { + pipeline.push(generateComputeStageFromComputedExpr(parameters.compute)); + } + + if (parameters.filter) { + pipeline.push(generateMatchFromFilterExpr(parameters.filter)); + } + + /* copy to count query */ + if (opts?.returnDataCountQuery || opts?.returnCountOnly) { + countPipeline = [...pipeline]; + } + + if (parameters.search) { + const searchExpr = generateSearchFromSearchExpr( + parameters.search, + opts?.regexSearchFields + ); + + pipeline.push(searchExpr); + countPipeline.push(searchExpr); + } + + if (parameters.skip) { + pipeline.push(generateSkipFromSkipExpr(parameters.skip)); + } + + if (parameters.top) { + pipeline.push(generateLimitFromTopExpr(parameters.top)); + } + + if (parameters.select) { + pipeline.push(generateProjectFromSelectExpr(parameters.select)); + } + + if (parameters.orderby) { + pipeline.push(generateSortFromOrderbyExpr(parameters.orderby)); + } + + //add default steps if pipline must not be empty - i.e. in mongoose an empty pipeline returns an error + if (!opts?.returnEmptyPipeline && pipeline.length == 0) { + pipeline.push( + { + $addFields: { + odatafyMongoDBTempField: "", + }, + }, + { + $project: { + odatafyMongoDBTempField: 0, + }, + } + ); + + countPipeline = [...pipeline]; + } + + countPipeline.push({ + $count: "count", + }); + + if (opts?.returnCountOnly) { + return countPipeline; + } + + if (opts?.returnDataCountQuery) { + return [ + { + $facet: { + data: pipeline, + countTmp: countPipeline, + }, + }, + { + $addFields: { + countTmp2: { + $first: "$countTmp", + }, + }, + }, + { + $project: { + data: "$data", + count: "$countTmp2.count", + }, + }, + ]; + } + + return pipeline; +} From a41dcbf8327eb9626a7d0410920fe3710b27f706 Mon Sep 17 00:00:00 2001 From: Robin Reyer Date: Tue, 23 Apr 2024 16:14:17 +0200 Subject: [PATCH 2/2] 0.0.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b95a24..b46c501 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "odatafy-mongodb", - "version": "0.0.10", + "version": "0.0.11", "description": "convert oData requests through odatafy to MongoDB queries ", "main": "./dist/index.js", "keywords": [