feat: added nested op

This commit is contained in:
Methapon2001 2024-01-17 11:21:41 +07:00
parent e655b9b325
commit ce22f77b32
No known key found for this signature in database
GPG key ID: 849924FEF46BD132
2 changed files with 43 additions and 21 deletions

View file

@ -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: {

View file

@ -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)),
},
};
};
}