-
Notifications
You must be signed in to change notification settings - Fork 83
feat(webui): Display search results in Presto UI. #1179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
aca6241
5eea062
d23ba77
af59d56
f3dec72
3a8caa0
e969603
d8bc69b
3c639fb
db8e2eb
4e055f5
5281937
527cb19
9cdcebb
ddaba31
085ba38
12222c2
2118902
90caa4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import { | ||
| useEffect, | ||
| useMemo, | ||
| } from "react"; | ||
|
|
||
| import VirtualTable from "../../../../../../components/VirtualTable"; | ||
| import useSearchStore from "../../../../SearchState/index"; | ||
| import {PrestoSearchResult} from "./typings"; | ||
| import {usePrestoSearchResults} from "./usePrestoSearchResults"; | ||
| import {getPrestoSearchResultsTableColumns} from "./utils"; | ||
|
|
||
|
|
||
| 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(); | ||
|
|
||
| const columns = useMemo( | ||
| () => getPrestoSearchResultsTableColumns(prestoSearchResults || []), | ||
| [prestoSearchResults] | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| const num = prestoSearchResults ? | ||
| prestoSearchResults.length : | ||
| 0; | ||
|
|
||
| updateNumSearchResultsTable(num); | ||
| }, [ | ||
| prestoSearchResults, | ||
| updateNumSearchResultsTable, | ||
| ]); | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return ( | ||
| <VirtualTable<PrestoSearchResult> | ||
| columns={columns} | ||
| dataSource={prestoSearchResults || []} | ||
| pagination={false} | ||
| rowKey={(record) => record._id} | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| scroll={{y: tableHeight}}/> | ||
| ); | ||
| }; | ||
|
|
||
| export default PrestoResultsVirtualTable; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| /** | ||
| * Structure of dynamic Presto search results data. | ||
| */ | ||
| interface PrestoSearchResult { | ||
| _id: string; | ||
| row: Record<string, unknown>; | ||
| } | ||
|
|
||
| export type {PrestoSearchResult}; |
| 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"; | ||
hoophalab marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| /** | ||
| * Custom hook to get Presto search results for the current searchJobId. | ||
| * | ||
| * @return | ||
| */ | ||
| const usePrestoSearchResults = () => { | ||
| const searchJobId = useSearchStore((state) => state.searchJobId); | ||
|
|
||
| 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}` | ||
| ); | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Retrieve 1k most recent results. | ||
| const options = { | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| sort: [ | ||
| [ | ||
| "_id", | ||
| "desc", | ||
| ], | ||
| ], | ||
| limit: SEARCH_MAX_NUM_RESULTS, | ||
| }; | ||
|
|
||
| const collection = new MongoSocketCollection(searchJobId); | ||
| return collection.find({}, options); | ||
| }, | ||
| [searchJobId] | ||
| ); | ||
|
|
||
| return searchResultsCursor; | ||
| }; | ||
|
|
||
| export {usePrestoSearchResults}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import {TableProps} from "antd"; | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import {PrestoSearchResult} from "./typings"; | ||
hoophalab marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| /** | ||
| * Generates dynamic columns configuration for Presto query engine. | ||
| * | ||
| * @param data Array of Presto search results | ||
| * @return | ||
| */ | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const getPrestoSearchResultsTableColumns = ( | ||
| data: PrestoSearchResult[] | ||
| ): NonNullable<TableProps<PrestoSearchResult>["columns"]> => { | ||
| if (0 === data.length || | ||
| "undefined" === typeof data[0] || | ||
| "undefined" === typeof data[0].row | ||
| ) { | ||
| return []; | ||
| } | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return Object.keys(data[0].row) | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .map((key) => ({ | ||
| dataIndex: [ | ||
| "row", | ||
| key, | ||
| ], | ||
| key: key, | ||
| title: key, | ||
| })); | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| export {getPrestoSearchResultsTableColumns}; | ||
| 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 | ||
| */ | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const SearchResultsVirtualTable = ({tableHeight}: SearchResultsVirtualTableProps) => { | ||
| const {updateNumSearchResultsTable} = useSearchStore(); | ||
| const searchResults = useSearchResults(); | ||
|
|
||
| useEffect(() => { | ||
| const num = searchResults ? | ||
| searchResults.length : | ||
| 0; | ||
|
|
||
| updateNumSearchResultsTable(num); | ||
| }, [ | ||
| searchResults, | ||
| updateNumSearchResultsTable, | ||
| ]); | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return ( | ||
| <VirtualTable<SearchResult> | ||
| columns={searchResultsTableColumns} | ||
| dataSource={searchResults || []} | ||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pagination={false} | ||
| rowKey={(record) => record._id.toString()} | ||
| scroll={{y: tableHeight}}/> | ||
| ); | ||
| }; | ||
|
|
||
| export default SearchResultsVirtualTable; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| /** | ||
| * Padding for the table to the bottom of the page. | ||
| */ | ||
| const TABLE_BOTTOM_PADDING = 75; | ||
|
|
||
| /** | ||
| * The maximum number of results to retrieve for a search. | ||
| */ | ||
| const SEARCH_MAX_NUM_RESULTS = 1000; | ||
|
|
||
| export { | ||
| SEARCH_MAX_NUM_RESULTS, | ||
| TABLE_BOTTOM_PADDING, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -146,6 +146,8 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => { | |
| throw error; | ||
| } | ||
|
|
||
| await mongoDb.createCollection(searchJobId); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this cannot happen in presto-client-node, but in case we change to a more async client, how about adding this comment:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think with the current code the situation you describe is not possible. see line here. Like if the data comes first, then it will just exit early and print a log, like it wont create a collection. I dont think the comment is neccesary since if it is actually possible which i doubt, then it will print error log
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should do better than only runtime correctness, but I'm fine if we don't add a comment here as it doesn't make the code better and we might forget to update comments in the future. |
||
|
|
||
hoophalab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| reply.code(StatusCodes.CREATED); | ||
|
|
||
| return {searchJobId}; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.