import { useEffect , useMemo , useState } from 'react' ; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey' ; import type { EuiDataGridColumn } from '@elastic/eui' ; import { isEsSearchResponse , isFieldHistogramsResponseSchema , } from '../../../common/api_schemas/type_guards' ; import { hasKeywordDuplicate , isKeywordDuplicate , removeKeywordPostfix , } from '../../../common/utils/field_utils' ; import type { EsSorting , UseIndexDataReturnType } from '../../shared_imports' ; import { getErrorMessage } from '../../../common/utils/errors' ; import { isDefaultQuery , matchAllQuery , PivotQuery } from '../common' ; import { SearchItems } from './use_search_items' ; import { useApi } from './use_api' ; import { useAppDependencies , useToastNotifications } from '../app_dependencies' ; import type { StepDefineExposedState } from '../sections/create_transform/components/step_define/common' ; import { isRuntimeMappings } from '../../../common/shared_imports' ; export const useIndexData = ( indexPattern , query , combinedRuntimeMappings ? ) : UseIndexDataReturnType => { const api = useApi ( ) ; const toastNotifications = useToastNotifications ( ) ; const { ml : { getFieldType , getDataGridSchemaFromKibanaFieldType , getDataGridSchemaFromESFieldType , getFieldsFromKibanaIndexPattern , showDataGridColumnChartErrorMessageToast , useDataGrid , useRenderCellValue , getProcessedFields , INDEX_STATUS , } , } = useAppDependencies ( ) ; const [ indexPatternFields , setIndexPatternFields ] = useState < string [ ] > ( ) ; const fetchDataGridSampleDocuments = async function ( ) { setErrorMessage ( '' ) ; setStatus ( INDEX_STATUS . LOADING ) ; const esSearchRequest = { index : indexPattern . title , body : { fields : [ '*' ] , _source : false , query : { function_score : { query : { match_all : { } } , random_score : { } , } , } , size : 500 , } , } ; const resp = await api . esSearch ( esSearchRequest ) ; if ( ! isEsSearchResponse ( resp ) ) { setErrorMessage ( getErrorMessage ( resp ) ) ; setStatus ( INDEX_STATUS . ERROR ) ; return ; } const isCrossClusterSearch = indexPattern . title . includes ( ':' ) ; const isMissingFields = resp . hits . hits . every ( ( d ) => typeof d . fields === 'undefined' ) ; const docs = resp . hits . hits . map ( ( d ) => getProcessedFields ( d . fields ?? { } ) ) ; const allKibanaIndexPatternFields = getFieldsFromKibanaIndexPattern ( indexPattern ) ; const populatedFields = [ ... new Set ( docs . map ( Object . keys ) . flat ( 1 ) ) ] . filter ( ( d ) => allKibanaIndexPatternFields . includes ( d ) ) . sort ( ) ; setCcsWarning ( isCrossClusterSearch && isMissingFields ) ; setStatus ( INDEX_STATUS . LOADED ) ; setIndexPatternFields ( populatedFields ) ; } ; useEffect ( ( ) => { fetchDataGridSampleDocuments ( ) ; } , [ ] ) ; const columns = useMemo ( ( ) => { if ( typeof indexPatternFields === 'undefined' ) { return [ ] ; } let result = [ ] ; if ( combinedRuntimeMappings !== undefined ) { result = Object . keys ( combinedRuntimeMappings ) . map ( ( fieldName ) => { const field = combinedRuntimeMappings [ fieldName ] ; const schema = getDataGridSchemaFromESFieldType ( field . type ) ; return { id : fieldName , schema } ; } ) ; } indexPatternFields . forEach ( ( id ) => { const field = indexPattern . fields . getByName ( id ) ; if ( ! field ?. runtimeField ) { const schema = getDataGridSchemaFromKibanaFieldType ( field ) ; result . push ( { id , schema } ) ; } } ) ; return result . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) ; } , [ indexPatternFields , indexPattern . fields , combinedRuntimeMappings , getDataGridSchemaFromESFieldType , getDataGridSchemaFromKibanaFieldType , ] ) ; const dataGrid = useDataGrid ( columns ) ; const { chartsVisible , pagination , resetPagination , setColumnCharts , setCcsWarning , setErrorMessage , setRowCount , setRowCountRelation , setStatus , setTableItems , sortingColumns , tableItems , } = dataGrid ; useEffect ( ( ) => { resetPagination ( ) ; } , [ JSON . stringify ( query ) ] ) ; const fetchDataGridData = async function ( ) { setErrorMessage ( '' ) ; setStatus ( INDEX_STATUS . LOADING ) ; const sort = sortingColumns . reduce ( ( s , column ) => { s [ column . id ] = { order : column . direction } ; return s ; } , { } as EsSorting ) ; const esSearchRequest = { index : indexPattern . title , body : { fields : [ '*' ] , _source : false , query : isDefaultQuery ( query ) ? matchAllQuery : query , from : pagination . pageIndex * pagination . pageSize , size : pagination . pageSize , ... ( Object . keys ( sort ) . length > 0 ? { sort } : { } ) , ... ( isRuntimeMappings ( combinedRuntimeMappings ) ? { runtime_mappings : combinedRuntimeMappings } : { } ) , } , } ; const resp = await api . esSearch ( esSearchRequest ) ; if ( ! isEsSearchResponse ( resp ) ) { setErrorMessage ( getErrorMessage ( resp ) ) ; setStatus ( INDEX_STATUS . ERROR ) ; return ; } const isCrossClusterSearch = indexPattern . title . includes ( ':' ) ; const isMissingFields = resp . hits . hits . every ( ( d ) => typeof d . fields === 'undefined' ) ; const docs = resp . hits . hits . map ( ( d ) => getProcessedFields ( d . fields ?? { } ) ) ; setCcsWarning ( isCrossClusterSearch && isMissingFields ) ; setRowCount ( typeof resp . hits . total === 'number' ? resp . hits . total : resp . hits . total ! . value ) ; setRowCountRelation ( typeof resp . hits . total === 'number' ? ( 'eq' as estypes . SearchTotalHitsRelation ) : resp . hits . total ! . relation ) ; setTableItems ( docs ) ; setStatus ( INDEX_STATUS . LOADED ) ; } ; const fetchColumnChartsData = async function ( ) { const allIndexPatternFieldNames = new Set ( indexPattern . fields . map ( ( f ) => f . name ) ) ; const columnChartsData = await api . getHistogramsForFields ( indexPattern . title , columns . filter ( ( cT ) => dataGrid . visibleColumns . includes ( cT . id ) ) . map ( ( cT ) => { const fieldName = cT . id ; return hasKeywordDuplicate ( fieldName , allIndexPatternFieldNames ) ? { fieldName : `${ fieldName }.keyword` , type : getFieldType ( undefined ) , } : { fieldName , type : getFieldType ( cT . schema ) , } ; } ) , isDefaultQuery ( query ) ? matchAllQuery : query , combinedRuntimeMappings ) ; if ( ! isFieldHistogramsResponseSchema ( columnChartsData ) ) { showDataGridColumnChartErrorMessageToast ( columnChartsData , toastNotifications ) ; return ; } setColumnCharts ( columnChartsData . map ( ( d ) => ( { ... d , ... ( isKeywordDuplicate ( d . id , allIndexPatternFieldNames ) ? { id : removeKeywordPostfix ( d . id ) } : { } ) , } ) ) ) ; } ; useEffect ( ( ) => { fetchDataGridData ( ) ; } , [ indexPattern . title , JSON . stringify ( [ query , pagination , sortingColumns , indexPatternFields , combinedRuntimeMappings , ] ) , ] ) ; useEffect ( ( ) => { if ( chartsVisible ) { fetchColumnChartsData ( ) ; } } , [ chartsVisible , indexPattern . title , JSON . stringify ( [ query , dataGrid . visibleColumns , combinedRuntimeMappings ] ) , ] ) ; const renderCellValue = useRenderCellValue ( indexPattern , pagination , tableItems ) ; return { ... dataGrid , renderCellValue , } ; } ;