feat: added nested op
This commit is contained in:
parent
e655b9b325
commit
ce22f77b32
2 changed files with 43 additions and 21 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import { Body, Controller, Post, Route, Security, SuccessResponse, Tags } from "tsoa";
|
||||
import HttpStatusCode from "../interfaces/http-status";
|
||||
import esClient from "../elasticsearch";
|
||||
import { Search } from "../interfaces/search";
|
||||
import { Search, SearchInfo, SearchOperator } from "../interfaces/search";
|
||||
import { StorageFile } from "../interfaces/storage-fs";
|
||||
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
||||
|
||||
const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;
|
||||
|
||||
|
|
@ -17,19 +18,23 @@ export class SearchController extends Controller {
|
|||
public async searchFile(@Body() search: Search): Promise<StorageFile[]> {
|
||||
const type = ["match", "match_phrase"] as const;
|
||||
|
||||
const searchMapCallback = (v: SearchInfo | SearchOperator): QueryDslQueryContainer => {
|
||||
if ("field" in v && "value" in v) {
|
||||
return { [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value } };
|
||||
}
|
||||
|
||||
return {
|
||||
bool: { must: v.AND?.map(searchMapCallback), should: v.OR?.map(searchMapCallback) },
|
||||
};
|
||||
};
|
||||
|
||||
const result = await esClient.search<StorageFile & { attachment: Record<string, string> }>({
|
||||
index: DEFAULT_INDEX,
|
||||
query: {
|
||||
bool: {
|
||||
must: search.AND?.map((v) => ({
|
||||
[type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value },
|
||||
})),
|
||||
should: search.OR?.map((v) => ({
|
||||
[type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value },
|
||||
})),
|
||||
must_not: {
|
||||
match: { hidden: true },
|
||||
},
|
||||
must: search.AND?.map(searchMapCallback),
|
||||
should: search.OR?.map(searchMapCallback),
|
||||
must_not: { match: { hidden: true } },
|
||||
},
|
||||
},
|
||||
post_filter: {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,32 @@
|
|||
export interface Search {
|
||||
AND?: {
|
||||
field: string;
|
||||
value: string;
|
||||
exact?: boolean;
|
||||
}[];
|
||||
OR?: {
|
||||
field: string;
|
||||
value: string;
|
||||
exact?: boolean;
|
||||
}[];
|
||||
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
|
||||
|
||||
export interface SearchInfo {
|
||||
field: string;
|
||||
value: string;
|
||||
exact?: boolean;
|
||||
}
|
||||
|
||||
export interface SearchOperator {
|
||||
AND?: (SearchInfo | SearchOperator)[];
|
||||
OR?: (SearchInfo | SearchOperator)[];
|
||||
}
|
||||
|
||||
export interface Search extends SearchOperator {
|
||||
recursive?: boolean;
|
||||
path?: string[];
|
||||
exact?: boolean;
|
||||
}
|
||||
|
||||
export function mapCallback(exact: boolean) {
|
||||
const type = ["match", "match_phrase"] as const;
|
||||
return (v: SearchInfo | SearchOperator): QueryDslQueryContainer => {
|
||||
return "field" in v && "value" in v
|
||||
? { [type[exact || v.exact ? 1 : 0]]: { [v.field]: v.value } }
|
||||
: {
|
||||
bool: {
|
||||
must: v.AND?.map(mapCallback(exact)),
|
||||
should: v.OR?.map(mapCallback(exact)),
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue