Public/EAI/Invoke-EAIRecordsQuery.ps1
|
<# .SYNOPSIS Searches Edwin records using the UI Query API. .DESCRIPTION Invoke-EAIRecordsQuery posts a filter-based search to POST /ui/query/records and returns matching records for events, alerts, or insights. Use -RequestBody to pass a complete JSON request when cmdlet parameters are insufficient. Run Get-EAIQueryField to list common query field names for -Field, -OrderField, and filters. Query field paths (for example meta.eventTimestamp) often differ from properties on returned records. .PARAMETER RecordType Record table to query: events, alerts, or insights. .PARAMETER Field Optional field names to return (for example _id, cf.eventName). When omitted, fields is sent as null and the API returns all available source fields (same as the Edwin UI). .PARAMETER Filter Optional filterCondition object from Build-EAIQueryFilter or a manual expression. When omitted, the Edwin UI default filter for the record type is used (last 24 hours and standard insightType handling). .PARAMETER Timezone IANA timezone for relative time filters. Defaults to the local system timezone. .PARAMETER Order Optional advanced sort clauses as hashtables or objects with field and type (asc or desc). Cannot be combined with -OrderField or -OrderDirection. .PARAMETER OrderField Field to sort by (for example meta.eventTimestamp). Defaults to the record-type timestamp field when -OrderDirection is specified alone. .PARAMETER OrderDirection Sort direction: asc or desc. Defaults to desc when -OrderField is specified alone. When neither order parameters are specified, results sort by the record-type timestamp field descending. .PARAMETER Size Maximum records to return (1-200). Omit to use the API default of 10. .PARAMETER ElasticQuery Optional raw OpenSearch query object (advanced). .PARAMETER RequestBody Complete request object or JSON string. When specified, other body parameters are ignored. .EXAMPLE Invoke-EAIRecordsQuery -RecordType events .EXAMPLE Invoke-EAIRecordsQuery -RecordType events -Field '_id','cf.eventName','cf.eventSeverity' .EXAMPLE $filter = Build-EAIQueryFilter -PassThru Invoke-EAIRecordsQuery -RecordType events -Field '_id','cf.eventName','cf.eventSeverity' -Filter $filter .EXAMPLE Invoke-EAIRecordsQuery -RecordType events ` -Field '_id','cf.eventName' ` -Filter (New-EAISdtFilterObject -Expression @{ WITHIN = @( (New-EAISdtFilterFieldReference -Field 'cf.eventTime' -Type 'long') @{ unit = 'hour'; duration = 24 } ) }) ` -Size 25 .EXAMPLE Invoke-EAIRecordsQuery -RecordType events -OrderField 'cf.eventName' -OrderDirection asc .PARAMETER AsResponse Returns the full API envelope (meta and results) instead of unwrapped record objects. .EXAMPLE Invoke-EAIRecordsQuery -RequestBody (Get-Content ./query.json -Raw) .EXAMPLE Get-EAIQueryField -RecordType events -Usage Order .EXAMPLE Invoke-EAIRecordsQuery -RecordType events -AsResponse .NOTES Use Connect-EAIAccount before running this command. Requires query_records API scope on the Edwin credentials. .INPUTS You can pipe a filter object to override the UI default when -RecordType is specified. .OUTPUTS By default, returns Edwin.Event, Edwin.Alert, or Edwin.Insight record objects. Use -AsResponse for the full Edwin.Query.Response envelope. #> function Invoke-EAIRecordsQuery { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Parameterized', ConfirmImpact = 'Medium')] param ( [Parameter(Mandatory, ParameterSetName = 'Parameterized')] [ValidateSet('events', 'alerts', 'insights')] [String]$RecordType, [Parameter(ParameterSetName = 'Parameterized')] [Alias('Fields')] [ArgumentCompleter({ param ($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) Get-EAIQueryFieldCompleterResults -WordToComplete $WordToComplete -RecordType $FakeBoundParameters['RecordType'] -Usage Return })] [String[]]$Field, [Parameter(ParameterSetName = 'Parameterized', ValueFromPipeline)] $Filter, [Parameter(ParameterSetName = 'Parameterized')] [String]$Timezone, [Parameter(ParameterSetName = 'Parameterized')] $Order, [Parameter(ParameterSetName = 'Parameterized')] [ArgumentCompleter({ param ($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) Get-EAIQueryFieldCompleterResults -WordToComplete $WordToComplete -RecordType $FakeBoundParameters['RecordType'] -Usage Order })] [String]$OrderField, [Parameter(ParameterSetName = 'Parameterized')] [ValidateSet('asc', 'desc', 'ASC', 'DESC')] [String]$OrderDirection, [Parameter(ParameterSetName = 'Parameterized')] [ValidateRange(1, 200)] [Nullable[int]]$Size, [Parameter(ParameterSetName = 'Parameterized')] $ElasticQuery, [Parameter(Mandatory, ParameterSetName = 'RequestBody')] $RequestBody, [Switch]$AsResponse ) if (-not (Test-EAIAuth -CallerPSCmdlet $PSCmdlet)) { return } if ($PSCmdlet.ParameterSetName -eq 'RequestBody') { if ($RequestBody -is [string]) { try { $bodyObject = $RequestBody | ConvertFrom-Json -ErrorAction Stop } catch { throw "RequestBody is not valid JSON: $($_.Exception.Message)" } } else { $bodyObject = $RequestBody } $body = ConvertTo-EAIQueryRequestJson -InputObject $bodyObject $target = 'Edwin records query (custom request body)' $queryErrorContext = Get-EAIRecordsQueryErrorContext -Payload $bodyObject } else { $buildParams = @{ RecordType = $RecordType Filter = $Filter } if ($PSBoundParameters.ContainsKey('Field')) { $buildParams.Field = $Field } if ($PSBoundParameters.ContainsKey('Timezone')) { $buildParams.Timezone = $Timezone } if ($PSBoundParameters.ContainsKey('Order')) { $buildParams.Order = $Order } if ($PSBoundParameters.ContainsKey('OrderField')) { $buildParams.OrderField = $OrderField } if ($PSBoundParameters.ContainsKey('OrderDirection')) { $buildParams.OrderDirection = $OrderDirection } if ($PSBoundParameters.ContainsKey('Size')) { $buildParams.Size = $Size } if ($PSBoundParameters.ContainsKey('ElasticQuery')) { $buildParams.ElasticQuery = $ElasticQuery } $payload = Build-EAIRecordsQueryPayload @buildParams $body = ConvertTo-EAIQueryRequestJson -InputObject $payload $target = "Edwin $RecordType records query" $queryErrorContext = Get-EAIRecordsQueryErrorContext -RecordType $RecordType -Payload $payload } $headers = New-EAIHeader -Auth $Script:EAIAuth -Method 'POST' $uri = Join-EAIUri -PortalUrl $Script:EAIAuth.PortalUrl -ResourcePath '/ui/query/records' $enableDebugLogging = $DebugPreference -ne 'SilentlyContinue' if ($PSCmdlet.ShouldProcess($target, 'Query Edwin records')) { Resolve-EAIDebugInfo -Url $uri -Headers $headers -Command $MyInvocation -Payload $body $response = Invoke-EAIRestMethod -Uri $uri -Method POST -Headers $headers -Auth $Script:EAIAuth -Body $body ` -CallerPSCmdlet $PSCmdlet -EnableDebugLogging:$enableDebugLogging -ErrorContext $queryErrorContext $outputRecordType = if ($PSCmdlet.ParameterSetName -eq 'Parameterized') { $RecordType } $projected = $false if ($PSCmdlet.ParameterSetName -eq 'Parameterized') { $projected = Test-EAIRecordsQueryUsesFieldProjection -FieldSpecified:$PSBoundParameters.ContainsKey('Field') -Field $Field } elseif ($null -ne $bodyObject -and $null -ne $bodyObject.fields -and @($bodyObject.fields).Count -gt 0) { $projected = $true } return Write-EAIQueryRecordsOutput -Response $response -RecordType $outputRecordType -AsResponse:$AsResponse -Projected:$projected } } |