Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type PrestoQueryJobCreationSchema,
submitQuery,
} from "../../../../api/presto-search";
import useSearchStore from "../../SearchState/";


/**
Expand All @@ -10,9 +11,11 @@ import {
* @param payload
*/
const handlePrestoQuerySubmit = (payload: PrestoQueryJobCreationSchema) => {
const store = useSearchStore.getState();
submitQuery(payload)
.then((result) => {
const {searchJobId} = result.data;
store.updateSearchJobId(searchJobId);
console.debug(
"Presto search job created - ",
"Search job ID:",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {useEffect} from "react";

import VirtualTable from "../../../../../components/VirtualTable";
import useSearchStore from "../../../SearchState/index";
import {
getPrestoSearchResultsTableColumns,
PrestoSearchResult,
} from "./typings";
import {usePrestoSearchResults} from "./usePrestoSearchResults";


interface PrestoResultsVirtualTableProps {
tableHeight: number;
}

/**
* Renders Presto search results in a virtual table.
*
* @param props
* @param props.tableHeight
* @return
*/
const PrestoResultsVirtualTable = ({tableHeight}: PrestoResultsVirtualTableProps) => {
const {updateNumSearchResultsTable} = useSearchStore();
const prestoSearchResults = usePrestoSearchResults();

useEffect(() => {
const num = prestoSearchResults ?
prestoSearchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
prestoSearchResults,
updateNumSearchResultsTable
]);

return (
<VirtualTable<PrestoSearchResult>
columns={getPrestoSearchResultsTableColumns(prestoSearchResults || [])}
dataSource={prestoSearchResults || []}
pagination={false}
rowKey={(record) => record._id}
scroll={{y: tableHeight}}/>
);
};

export default PrestoResultsVirtualTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {TableProps} from "antd";


/**
* Structure of Presto search results data (dynamic properties).
*/
interface PrestoSearchResult {
_id: string;
row: Record<string, unknown>;
}

/**
* Columns configuration for Presto query engine (dynamic based on data).
*
* @param data Array of Presto search results
* @return
*/
const getPrestoSearchResultsTableColumns = (
data: PrestoSearchResult[]
): NonNullable<TableProps<PrestoSearchResult>["columns"]> => {
if (0 === data.length || "undefined" === typeof data[0] || "undefined" === typeof data[0].row) {
return [];
}

return Object.keys(data[0].row)
.map((key) => ({
dataIndex: ["row",
key],
key: key,
title: key,
}));
};

export type {PrestoSearchResult};
export {getPrestoSearchResultsTableColumns};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import MongoSocketCollection from "../../../../../api/socket/MongoSocketCollection";
import {useCursor} from "../../../../../api/socket/useCursor";
import useSearchStore, {SEARCH_STATE_DEFAULT} from "../../../SearchState/index";
import {SEARCH_MAX_NUM_RESULTS} from "../typings";
import {PrestoSearchResult} from "./typings";


/**
* Custom hook to get Presto search results for the current searchJobId.
*
* @return
*/
const usePrestoSearchResults = () => {
const {searchJobId} = useSearchStore();

const searchResultsCursor = useCursor<PrestoSearchResult>(
() => {
// If there is no active search job, there are no results to fetch. The cursor will
// return null.
if (searchJobId === SEARCH_STATE_DEFAULT.searchJobId) {
return null;
}

console.log(
`Subscribing to updates to Presto search results with job ID: ${searchJobId}`
);

// Retrieve 1k most recent results.
const options = {
sort: [
[
"_id",
"desc",
],
],
limit: SEARCH_MAX_NUM_RESULTS,
};

const collection = new MongoSocketCollection(searchJobId.toString());
return collection.find({}, options);
},
[searchJobId]
);

return searchResultsCursor;
};

export {usePrestoSearchResults};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {useEffect} from "react";

import VirtualTable from "../../../../components/VirtualTable";
import useSearchStore from "../../SearchState/index";
import {
SearchResult,
searchResultsTableColumns,
} from "./typings";
import {useSearchResults} from "./useSearchResults";


interface SearchResultsVirtualTableProps {
tableHeight: number;
}

/**
* Renders search results in a virtual table.
*
* @param props
* @param props.tableHeight
* @return
*/
const SearchResultsVirtualTable = ({tableHeight}: SearchResultsVirtualTableProps) => {
const {updateNumSearchResultsTable} = useSearchStore();
const searchResults = useSearchResults();

useEffect(() => {
const num = searchResults ?
searchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
searchResults,
updateNumSearchResultsTable,
]);

return (
<VirtualTable<SearchResult>
columns={searchResultsTableColumns}
dataSource={searchResults || []}
pagination={false}
rowKey={(record) => record._id.toString()}
scroll={{y: tableHeight}}/>
);
};

export default SearchResultsVirtualTable;
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import {
useState,
} from "react";

import VirtualTable from "../../../../components/VirtualTable";
import useSearchStore from "../../SearchState/index";
import {
SearchResult,
searchResultsTableColumns,
TABLE_BOTTOM_PADDING,
} from "./typings";
import {useSearchResults} from "./useSearchResults";
CLP_QUERY_ENGINES,
SETTINGS_QUERY_ENGINE,
} from "../../../../config";
import PrestoResultsVirtualTable from "./Presto/PrestoResultsVirtualTable";
import SearchResultsVirtualTable from "./SearchResultsVirtualTable";
import {TABLE_BOTTOM_PADDING} from "./typings";


/**
Expand All @@ -20,22 +19,9 @@ import {useSearchResults} from "./useSearchResults";
* @return
*/
const SearchResultsTable = () => {
const {updateNumSearchResultsTable} = useSearchStore();
const searchResults = useSearchResults();
const [tableHeight, setTableHeight] = useState<number>(0);
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const num = searchResults ?
searchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
searchResults,
updateNumSearchResultsTable,
]);

// Antd table requires a fixed height for virtual scrolling. The effect sets a fixed height
// based on the window height, container top, and fixed padding.
useEffect(() => {
Expand All @@ -60,12 +46,13 @@ const SearchResultsTable = () => {
ref={containerRef}
style={{outline: "none"}}
>
<VirtualTable<SearchResult>
columns={searchResultsTableColumns}
dataSource={searchResults || []}
pagination={false}
rowKey={(record) => record._id.toString()}
scroll={{y: tableHeight}}/>
{CLP_QUERY_ENGINES.PRESTO === SETTINGS_QUERY_ENGINE ?
(
<PrestoResultsVirtualTable tableHeight={tableHeight}/>
) :
(
<SearchResultsVirtualTable tableHeight={tableHeight}/>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface SearchResult {
}

/**
* Columns configuration for the seach results table.
* Columns configuration for the search results table.
*/
const searchResultsTableColumns: NonNullable<TableProps<SearchResult>["columns"]> = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
throw error;
}

await mongoDb.createCollection(searchJobId.toString());

reply.code(StatusCodes.CREATED);

return {searchJobId};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const prestoRowToObject = (
obj[col.name] = row[idx];
});

return obj;
return {row: obj};
};

/**
Expand All @@ -38,7 +38,7 @@ const insertPrestoRowsToMongo = (
columns: {name: string}[],
searchJobId: string,
mongoDb: Db
): Promise<InsertManyResult<Document>> => {
): Promise<InsertManyResult> => {
const collection = mongoDb.collection(searchJobId);
const resultDocs = data.map((row) => prestoRowToObject(row, columns));
return collection.insertMany(resultDocs);
Expand Down