fix: swagger recursive type not working
This commit is contained in:
parent
ce22f77b32
commit
c1eaeb5c64
4 changed files with 114 additions and 57 deletions
|
|
@ -1,9 +1,10 @@
|
||||||
import { Body, Controller, Post, Route, Security, SuccessResponse, Tags } from "tsoa";
|
import { Body, Controller, Post, Route, Security, SuccessResponse, Tags } from "tsoa";
|
||||||
import HttpStatusCode from "../interfaces/http-status";
|
import HttpStatusCode from "../interfaces/http-status";
|
||||||
import esClient from "../elasticsearch";
|
import esClient from "../elasticsearch";
|
||||||
import { Search, SearchInfo, SearchOperator } from "../interfaces/search";
|
import { Search, SearchInfo, SearchOperator, SearchOptions } from "../interfaces/search";
|
||||||
import { StorageFile } from "../interfaces/storage-fs";
|
import { StorageFile } from "../interfaces/storage-fs";
|
||||||
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
||||||
|
import HttpError from "../interfaces/http-error";
|
||||||
|
|
||||||
const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;
|
const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;
|
||||||
|
|
||||||
|
|
@ -15,7 +16,26 @@ export class SearchController extends Controller {
|
||||||
@Tags("Search")
|
@Tags("Search")
|
||||||
@Security("bearerAuth")
|
@Security("bearerAuth")
|
||||||
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
|
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
|
||||||
public async searchFile(@Body() search: Search): Promise<StorageFile[]> {
|
public async searchFile(
|
||||||
|
@Body()
|
||||||
|
body: {
|
||||||
|
AND?: (
|
||||||
|
| SearchInfo
|
||||||
|
| {
|
||||||
|
AND?: unknown;
|
||||||
|
OR?: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
OR?: (
|
||||||
|
| SearchInfo
|
||||||
|
| {
|
||||||
|
AND?: unknown;
|
||||||
|
OR?: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
} & SearchOptions,
|
||||||
|
): Promise<StorageFile[]> {
|
||||||
|
const search = body as Search;
|
||||||
const type = ["match", "match_phrase"] as const;
|
const type = ["match", "match_phrase"] as const;
|
||||||
|
|
||||||
const searchMapCallback = (v: SearchInfo | SearchOperator): QueryDslQueryContainer => {
|
const searchMapCallback = (v: SearchInfo | SearchOperator): QueryDslQueryContainer => {
|
||||||
|
|
@ -23,9 +43,16 @@ export class SearchController extends Controller {
|
||||||
return { [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value } };
|
return { [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value } };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
if ("AND" in v || "OR" in v) {
|
||||||
bool: { must: v.AND?.map(searchMapCallback), should: v.OR?.map(searchMapCallback) },
|
return {
|
||||||
};
|
bool: { must: v.AND?.map(searchMapCallback), should: v.OR?.map(searchMapCallback) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new HttpError(
|
||||||
|
HttpStatusCode.UNPROCESSABLE_ENTITY,
|
||||||
|
"ข้อมูลค้นหาไม่ถูกต้อง กรุณาตรวจสอบอีกครั้ง",
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await esClient.search<StorageFile & { attachment: Record<string, string> }>({
|
const result = await esClient.search<StorageFile & { attachment: Record<string, string> }>({
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
||||||
|
|
||||||
|
export interface SearchOptions {
|
||||||
|
recursive?: boolean;
|
||||||
|
path?: string[];
|
||||||
|
exact?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SearchInfo {
|
export interface SearchInfo {
|
||||||
field: string;
|
field: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
|
@ -11,11 +17,7 @@ export interface SearchOperator {
|
||||||
OR?: (SearchInfo | SearchOperator)[];
|
OR?: (SearchInfo | SearchOperator)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Search extends SearchOperator {
|
export type Search = SearchOperator & SearchOptions;
|
||||||
recursive?: boolean;
|
|
||||||
path?: string[];
|
|
||||||
exact?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapCallback(exact: boolean) {
|
export function mapCallback(exact: boolean) {
|
||||||
const type = ["match", "match_phrase"] as const;
|
const type = ["match", "match_phrase"] as const;
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,22 @@ const models: TsoaRoute.Models = {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
},
|
},
|
||||||
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
||||||
"Search": {
|
"SearchInfo": {
|
||||||
"dataType": "refObject",
|
"dataType": "refObject",
|
||||||
"properties": {
|
"properties": {
|
||||||
"AND": {"dataType":"array","array":{"dataType":"nestedObjectLiteral","nestedProperties":{"exact":{"dataType":"boolean"},"value":{"dataType":"string","required":true},"field":{"dataType":"string","required":true}}}},
|
"field": {"dataType":"string","required":true},
|
||||||
"OR": {"dataType":"array","array":{"dataType":"nestedObjectLiteral","nestedProperties":{"exact":{"dataType":"boolean"},"value":{"dataType":"string","required":true},"field":{"dataType":"string","required":true}}}},
|
"value": {"dataType":"string","required":true},
|
||||||
"exact": {"dataType":"boolean"},
|
"exact": {"dataType":"boolean"},
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
},
|
||||||
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
||||||
|
"SearchOptions": {
|
||||||
|
"dataType": "refObject",
|
||||||
|
"properties": {
|
||||||
"recursive": {"dataType":"boolean"},
|
"recursive": {"dataType":"boolean"},
|
||||||
"path": {"dataType":"array","array":{"dataType":"string"}},
|
"path": {"dataType":"array","array":{"dataType":"string"}},
|
||||||
|
"exact": {"dataType":"boolean"},
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
},
|
},
|
||||||
|
|
@ -177,7 +185,7 @@ export function RegisterRoutes(app: Router) {
|
||||||
|
|
||||||
function SearchController_searchFile(request: any, response: any, next: any) {
|
function SearchController_searchFile(request: any, response: any, next: any) {
|
||||||
const args = {
|
const args = {
|
||||||
search: {"in":"body","name":"search","required":true,"ref":"Search"},
|
body: {"in":"body","name":"body","required":true,"dataType":"intersection","subSchemas":[{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"SearchInfo"},{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"any"},"AND":{"dataType":"any"}}}]}},"AND":{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"SearchInfo"},{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"any"},"AND":{"dataType":"any"}}}]}}}},{"ref":"SearchOptions"}]},
|
||||||
};
|
};
|
||||||
|
|
||||||
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
||||||
|
|
|
||||||
|
|
@ -110,53 +110,27 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"Search": {
|
"SearchInfo": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"AND": {
|
"field": {
|
||||||
"items": {
|
"type": "string"
|
||||||
"properties": {
|
|
||||||
"exact": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"field": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"value",
|
|
||||||
"field"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
},
|
||||||
"OR": {
|
"value": {
|
||||||
"items": {
|
"type": "string"
|
||||||
"properties": {
|
|
||||||
"exact": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"field": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"value",
|
|
||||||
"field"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
},
|
||||||
"exact": {
|
"exact": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"field",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"SearchOptions": {
|
||||||
|
"properties": {
|
||||||
"recursive": {
|
"recursive": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
|
@ -165,6 +139,9 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
},
|
||||||
|
"exact": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -617,7 +594,50 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/Search"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"OR": {
|
||||||
|
"items": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SearchInfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"OR": {},
|
||||||
|
"AND": {}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"AND": {
|
||||||
|
"items": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SearchInfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"OR": {},
|
||||||
|
"AND": {}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SearchOptions"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue