mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution][Elastic AI Assistant] Adds Knowledge Base (#166570)
## Summary Advanced Settings to enable the Knowledge Base is currently behind the same code toggle introduced in https://github.com/elastic/kibana/pull/164908, please modify `assistantLangChain` to be `true` to enable the Advanced Settings and Knowledge Base options:1dee16e061/x-pack/plugins/security_solution/public/assistant/provider.tsx (L55)
When the above modification is present, a new `Advanced Settings` UI is available within the Assistant that enables the ability to turn on and configure the Knowledge Base, and also add the requisite `ES|QL` Knowledge Base resources. <p align="center"> <img width="500" src="3abab422
-9a85-45f6-8b0b-854ed7383d1c" /> </p> Once enabled, the Assistant will query the Knowledge Base using a `ConversationalRetrievalQAChain`, by means of the ELSER specific `ElasticsearchStore` LangChain `VectorStore` abstraction: <p align="center"> <img width="500" src="a529faab
-948c-40f1-bc11-7a39b1766c7f" /> </p> ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials * TBD - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [X] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
8e800eec5a
commit
f5b09864b8
172 changed files with 5593 additions and 70 deletions
|
@ -923,7 +923,7 @@
|
|||
"jsonwebtoken": "^9.0.0",
|
||||
"jsts": "^1.6.2",
|
||||
"kea": "^2.4.2",
|
||||
"langchain": "^0.0.132",
|
||||
"langchain": "^0.0.151",
|
||||
"launchdarkly-js-client-sdk": "^2.22.1",
|
||||
"launchdarkly-node-server-sdk": "^6.4.2",
|
||||
"load-json-file": "^6.2.0",
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common';
|
||||
|
||||
import { HttpSetup } from '@kbn/core-http-browser';
|
||||
import type { Message } from '../assistant_context/types';
|
||||
import { Conversation } from '../assistant_context/types';
|
||||
import { HttpSetup, IHttpFetchError } from '@kbn/core-http-browser';
|
||||
|
||||
import type { Conversation, Message } from '../assistant_context/types';
|
||||
import { API_ERROR } from './translations';
|
||||
import { MODEL_GPT_3_5_TURBO } from '../connectorland/models/model_selector/model_selector';
|
||||
|
||||
|
@ -86,3 +86,121 @@ export const fetchConnectorExecuteAction = async ({
|
|||
return API_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
export interface GetKnowledgeBaseStatusParams {
|
||||
http: HttpSetup;
|
||||
resource?: string;
|
||||
signal?: AbortSignal | undefined;
|
||||
}
|
||||
|
||||
export interface GetKnowledgeBaseStatusResponse {
|
||||
elser_exists: boolean;
|
||||
esql_exists?: boolean;
|
||||
index_exists: boolean;
|
||||
pipeline_exists: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* API call for getting the status of the Knowledge Base. Provide
|
||||
* a resource to include the status of that specific resource.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {string} [options.resource] - Resource to get the status of, otherwise status of overall KB
|
||||
* @param {AbortSignal} [options.signal] - AbortSignal
|
||||
*
|
||||
* @returns {Promise<GetKnowledgeBaseStatusResponse | IHttpFetchError>}
|
||||
*/
|
||||
export const getKnowledgeBaseStatus = async ({
|
||||
http,
|
||||
resource,
|
||||
signal,
|
||||
}: GetKnowledgeBaseStatusParams): Promise<GetKnowledgeBaseStatusResponse | IHttpFetchError> => {
|
||||
try {
|
||||
const path = `/internal/elastic_assistant/knowledge_base/${resource || ''}`;
|
||||
const response = await http.fetch(path, {
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
|
||||
return response as GetKnowledgeBaseStatusResponse;
|
||||
} catch (error) {
|
||||
return error as IHttpFetchError;
|
||||
}
|
||||
};
|
||||
|
||||
export interface PostKnowledgeBaseParams {
|
||||
http: HttpSetup;
|
||||
resource?: string;
|
||||
signal?: AbortSignal | undefined;
|
||||
}
|
||||
|
||||
export interface PostKnowledgeBaseResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* API call for setting up the Knowledge Base. Provide a resource to set up a specific resource.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {string} [options.resource] - Resource to be added to the KB, otherwise sets up the base KB
|
||||
* @param {AbortSignal} [options.signal] - AbortSignal
|
||||
*
|
||||
* @returns {Promise<PostKnowledgeBaseResponse | IHttpFetchError>}
|
||||
*/
|
||||
export const postKnowledgeBase = async ({
|
||||
http,
|
||||
resource,
|
||||
signal,
|
||||
}: PostKnowledgeBaseParams): Promise<PostKnowledgeBaseResponse | IHttpFetchError> => {
|
||||
try {
|
||||
const path = `/internal/elastic_assistant/knowledge_base/${resource || ''}`;
|
||||
const response = await http.fetch(path, {
|
||||
method: 'POST',
|
||||
signal,
|
||||
});
|
||||
|
||||
return response as PostKnowledgeBaseResponse;
|
||||
} catch (error) {
|
||||
return error as IHttpFetchError;
|
||||
}
|
||||
};
|
||||
|
||||
export interface DeleteKnowledgeBaseParams {
|
||||
http: HttpSetup;
|
||||
resource?: string;
|
||||
signal?: AbortSignal | undefined;
|
||||
}
|
||||
|
||||
export interface DeleteKnowledgeBaseResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* API call for deleting the Knowledge Base. Provide a resource to delete that specific resource.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {string} [options.resource] - Resource to be deleted from the KB, otherwise delete the entire KB
|
||||
* @param {AbortSignal} [options.signal] - AbortSignal
|
||||
*
|
||||
* @returns {Promise<DeleteKnowledgeBaseResponse | IHttpFetchError>}
|
||||
*/
|
||||
export const deleteKnowledgeBase = async ({
|
||||
http,
|
||||
resource,
|
||||
signal,
|
||||
}: DeleteKnowledgeBaseParams): Promise<DeleteKnowledgeBaseResponse | IHttpFetchError> => {
|
||||
try {
|
||||
const path = `/internal/elastic_assistant/knowledge_base/${resource || ''}`;
|
||||
const response = await http.fetch(path, {
|
||||
method: 'DELETE',
|
||||
signal,
|
||||
});
|
||||
|
||||
return response as DeleteKnowledgeBaseResponse;
|
||||
} catch (error) {
|
||||
return error as IHttpFetchError;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ export const SETTINGS_TITLE = i18n.translate(
|
|||
export const SETTINGS_DESCRIPTION = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.conversations.settings.settingsDescription',
|
||||
{
|
||||
defaultMessage: 'Create and manage conversations with the Elastic AI Assistant',
|
||||
defaultMessage: 'Create and manage conversations with the Elastic AI Assistant.',
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export const SETTINGS_DESCRIPTION = i18n.translate(
|
|||
'xpack.elasticAssistant.assistant.promptEditor.systemPrompt.settings.settingsDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Create and manage System Prompts. System Prompts are configurable chunks of context that are always sent for a given conversations.',
|
||||
'Create and manage System Prompts. System Prompts are configurable chunks of context that are always sent for a given conversation.',
|
||||
}
|
||||
);
|
||||
export const ADD_SYSTEM_PROMPT_MODAL_TITLE = i18n.translate(
|
||||
|
|
|
@ -5,19 +5,130 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFormRow, EuiTitle, EuiText, EuiHorizontalRule, EuiSpacer } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
EuiFormRow,
|
||||
EuiTitle,
|
||||
EuiText,
|
||||
EuiTextColor,
|
||||
EuiHorizontalRule,
|
||||
EuiLoadingSpinner,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
EuiToolTip,
|
||||
EuiSwitchEvent,
|
||||
EuiLink,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import * as i18n from './translations';
|
||||
import { useKnowledgeBaseStatus } from '../../../knowledge_base/use_knowledge_base_status/use_knowledge_base_status';
|
||||
import { useAssistantContext } from '../../../assistant_context';
|
||||
import { useSetupKnowledgeBase } from '../../../knowledge_base/use_setup_knowledge_base/use_setup_knowledge_base';
|
||||
import { useDeleteKnowledgeBase } from '../../../knowledge_base/use_delete_knowledge_base/use_delete_knowledge_base';
|
||||
|
||||
const ESQL_RESOURCE = 'esql';
|
||||
interface Props {
|
||||
onAdvancedSettingsChange?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced Settings -- your catch-all container for settings that don't have a home elsewhere.
|
||||
* Advanced Settings -- enable and disable LangChain integration, Knowledge Base, and ESQL KB Documents
|
||||
*/
|
||||
export const AdvancedSettings: React.FC<Props> = React.memo(({ onAdvancedSettingsChange }) => {
|
||||
const { http, assistantLangChain } = useAssistantContext();
|
||||
const {
|
||||
data: kbStatus,
|
||||
isLoading,
|
||||
isFetching,
|
||||
} = useKnowledgeBaseStatus({ http, resource: ESQL_RESOURCE });
|
||||
const { mutate: setupKB, isLoading: isSettingUpKB } = useSetupKnowledgeBase({ http });
|
||||
const { mutate: deleteKB, isLoading: isDeletingUpKB } = useDeleteKnowledgeBase({ http });
|
||||
|
||||
const [isLangChainEnabled, setIsLangChainEnabled] = useState(assistantLangChain);
|
||||
const isKnowledgeBaseEnabled =
|
||||
(kbStatus?.index_exists && kbStatus?.pipeline_exists && kbStatus?.elser_exists) ?? false;
|
||||
const isESQLEnabled = kbStatus?.esql_exists ?? false;
|
||||
|
||||
const isLoadingKb = isLoading || isFetching || isSettingUpKB || isDeletingUpKB;
|
||||
const isKnowledgeBaseAvailable = isLangChainEnabled && kbStatus?.elser_exists;
|
||||
const isESQLAvailable = isLangChainEnabled && isKnowledgeBaseAvailable && isKnowledgeBaseEnabled;
|
||||
|
||||
const onEnableKnowledgeBaseChange = useCallback(
|
||||
(event: EuiSwitchEvent) => {
|
||||
if (event.target.checked) {
|
||||
setupKB();
|
||||
} else {
|
||||
deleteKB();
|
||||
}
|
||||
},
|
||||
[deleteKB, setupKB]
|
||||
);
|
||||
|
||||
const onEnableESQLChange = useCallback(
|
||||
(event: EuiSwitchEvent) => {
|
||||
if (event.target.checked) {
|
||||
setupKB(ESQL_RESOURCE);
|
||||
} else {
|
||||
deleteKB(ESQL_RESOURCE);
|
||||
}
|
||||
},
|
||||
[deleteKB, setupKB]
|
||||
);
|
||||
|
||||
const langchainSwitch = useMemo(() => {
|
||||
return (
|
||||
<EuiSwitch
|
||||
checked={isLangChainEnabled}
|
||||
compressed
|
||||
disabled={true} // Advanced settings only shown if assistantLangChain=true, remove when storing to localstorage as ui feature toggle
|
||||
label={i18n.LANNGCHAIN_LABEL}
|
||||
onChange={() => setIsLangChainEnabled(!isLangChainEnabled)}
|
||||
showLabel={false}
|
||||
/>
|
||||
);
|
||||
}, [isLangChainEnabled]);
|
||||
|
||||
const knowledgeBaseSwitch = useMemo(() => {
|
||||
return isLoadingKb ? (
|
||||
<EuiLoadingSpinner size="s" />
|
||||
) : (
|
||||
<EuiToolTip
|
||||
position={'right'}
|
||||
content={!isKnowledgeBaseAvailable ? i18n.KNOWLEDGE_BASE_LABEL_TOOLTIP : undefined}
|
||||
>
|
||||
<EuiSwitch
|
||||
showLabel={false}
|
||||
label={i18n.KNOWLEDGE_BASE_LABEL}
|
||||
checked={isKnowledgeBaseEnabled}
|
||||
disabled={!isKnowledgeBaseAvailable}
|
||||
onChange={onEnableKnowledgeBaseChange}
|
||||
compressed
|
||||
/>
|
||||
</EuiToolTip>
|
||||
);
|
||||
}, [isLoadingKb, isKnowledgeBaseAvailable, isKnowledgeBaseEnabled, onEnableKnowledgeBaseChange]);
|
||||
|
||||
const esqlSwitch = useMemo(() => {
|
||||
return isLoadingKb ? (
|
||||
<EuiLoadingSpinner size="s" />
|
||||
) : (
|
||||
<EuiToolTip
|
||||
position={'right'}
|
||||
content={!isESQLAvailable ? i18n.ESQL_LABEL_TOOLTIP : undefined}
|
||||
>
|
||||
<EuiSwitch
|
||||
showLabel={false}
|
||||
label={i18n.ESQL_LABEL}
|
||||
checked={isESQLEnabled}
|
||||
disabled={!isESQLAvailable}
|
||||
onChange={onEnableESQLChange}
|
||||
compressed
|
||||
/>
|
||||
</EuiToolTip>
|
||||
);
|
||||
}, [isLoadingKb, isESQLAvailable, isESQLEnabled, onEnableESQLChange]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiTitle size={'s'}>
|
||||
|
@ -29,15 +140,52 @@ export const AdvancedSettings: React.FC<Props> = React.memo(({ onAdvancedSetting
|
|||
|
||||
<EuiHorizontalRule margin={'s'} />
|
||||
|
||||
<EuiFormRow display="rowCompressed" label={'Disable LocalStorage'}>
|
||||
<>{'Disable LocalStorage'}</>
|
||||
<EuiFormRow display="columnCompressedSwitch" label={i18n.LANNGCHAIN_LABEL}>
|
||||
{langchainSwitch}
|
||||
</EuiFormRow>
|
||||
<EuiFormRow display="rowCompressed" label={'Clear LocalStorage'}>
|
||||
<>{'Clear LocalStorage'}</>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiTextColor color={'subdued'}>{i18n.LANNGCHAIN_DESCRIPTION}</EuiTextColor>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFormRow
|
||||
display="columnCompressedSwitch"
|
||||
label={i18n.KNOWLEDGE_BASE_LABEL}
|
||||
isDisabled={!isKnowledgeBaseAvailable}
|
||||
>
|
||||
{knowledgeBaseSwitch}
|
||||
</EuiFormRow>
|
||||
<EuiFormRow display="rowCompressed" label={'Reset Something Else'}>
|
||||
<>{'Reset Something Else'}</>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiTextColor color={'subdued'}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Initializes a local knowledge base for saving and retrieving relevant context for your conversations. Note: ELSER must be configured and started. {seeDocs}"
|
||||
id="xpack.elasticAssistant.assistant.settings.advancedSettings.knowledgeBaseDescription"
|
||||
values={{
|
||||
seeDocs: (
|
||||
<EuiLink
|
||||
external
|
||||
href={
|
||||
'https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html#download-deploy-elser'
|
||||
}
|
||||
target="_blank"
|
||||
>
|
||||
{i18n.KNOWLEDGE_BASE_DESCRIPTION_ELSER_LEARN_MORE}
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EuiTextColor>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFormRow
|
||||
isDisabled={!isESQLAvailable}
|
||||
display="columnCompressedSwitch"
|
||||
label={i18n.ESQL_LABEL}
|
||||
>
|
||||
{esqlSwitch}
|
||||
</EuiFormRow>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiTextColor color={'subdued'}>{i18n.ESQL_DESCRIPTION}</EuiTextColor>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -16,6 +16,64 @@ export const SETTINGS_TITLE = i18n.translate(
|
|||
export const SETTINGS_DESCRIPTION = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.settingsDescription',
|
||||
{
|
||||
defaultMessage: "They're not further along, they just have a different set of problems.",
|
||||
defaultMessage: 'Additional knobs and dials for the Elastic AI Assistant.',
|
||||
}
|
||||
);
|
||||
|
||||
export const LANNGCHAIN_LABEL = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.langChainLabel',
|
||||
{
|
||||
defaultMessage: 'Experimental LangChain Integration',
|
||||
}
|
||||
);
|
||||
|
||||
export const LANNGCHAIN_DESCRIPTION = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.langChainDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enables advanced features and workflows like the Knowledge Base, Functions, Memories, and advanced agent and chain configurations. ',
|
||||
}
|
||||
);
|
||||
|
||||
export const KNOWLEDGE_BASE_LABEL = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.knowledgeBaseLabel',
|
||||
{
|
||||
defaultMessage: 'Knowledge Base',
|
||||
}
|
||||
);
|
||||
|
||||
export const KNOWLEDGE_BASE_LABEL_TOOLTIP = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.knowledgeBaseLabelTooltip',
|
||||
{
|
||||
defaultMessage: 'Requires ELSER to be configured and started.',
|
||||
}
|
||||
);
|
||||
|
||||
export const KNOWLEDGE_BASE_DESCRIPTION_ELSER_LEARN_MORE = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.knowledgeBaseElserLearnMoreDescription',
|
||||
{
|
||||
defaultMessage: 'Learn more.',
|
||||
}
|
||||
);
|
||||
|
||||
export const ESQL_LABEL = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.esqlLabel',
|
||||
{
|
||||
defaultMessage: 'ES|QL Knowledge Base Documents',
|
||||
}
|
||||
);
|
||||
|
||||
export const ESQL_LABEL_TOOLTIP = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.esqlTooltip',
|
||||
{
|
||||
defaultMessage: 'Requires `Knowledge Base` to be enabled.',
|
||||
}
|
||||
);
|
||||
|
||||
export const ESQL_DESCRIPTION = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.advancedSettings.esqlDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Loads ES|QL documentation and language files into the Knowledge Base for use in generating ES|QL queries.',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -44,7 +44,6 @@ export const CONVERSATIONS_TAB = 'CONVERSATION_TAB' as const;
|
|||
export const QUICK_PROMPTS_TAB = 'QUICK_PROMPTS_TAB' as const;
|
||||
export const SYSTEM_PROMPTS_TAB = 'SYSTEM_PROMPTS_TAB' as const;
|
||||
export const ANONYMIZATION_TAB = 'ANONYMIZATION_TAB' as const;
|
||||
export const FUNCTIONS_TAB = 'FUNCTIONS_TAB' as const;
|
||||
export const ADVANCED_TAB = 'ADVANCED_TAB' as const;
|
||||
|
||||
export type SettingsTabs =
|
||||
|
@ -52,7 +51,6 @@ export type SettingsTabs =
|
|||
| typeof QUICK_PROMPTS_TAB
|
||||
| typeof SYSTEM_PROMPTS_TAB
|
||||
| typeof ANONYMIZATION_TAB
|
||||
| typeof FUNCTIONS_TAB
|
||||
| typeof ADVANCED_TAB;
|
||||
interface Props {
|
||||
defaultConnectorId?: string;
|
||||
|
@ -78,8 +76,13 @@ export const AssistantSettings: React.FC<Props> = React.memo(
|
|||
selectedConversation: defaultSelectedConversation,
|
||||
setSelectedConversationId,
|
||||
}) => {
|
||||
const { actionTypeRegistry, http, selectedSettingsTab, setSelectedSettingsTab } =
|
||||
useAssistantContext();
|
||||
const {
|
||||
actionTypeRegistry,
|
||||
assistantLangChain,
|
||||
http,
|
||||
selectedSettingsTab,
|
||||
setSelectedSettingsTab,
|
||||
} = useAssistantContext();
|
||||
const {
|
||||
conversationSettings,
|
||||
defaultAllow,
|
||||
|
@ -235,6 +238,16 @@ export const AssistantSettings: React.FC<Props> = React.memo(
|
|||
>
|
||||
<EuiIcon type="eyeClosed" size="l" />
|
||||
</EuiKeyPadMenuItem>
|
||||
{assistantLangChain && (
|
||||
<EuiKeyPadMenuItem
|
||||
id={ADVANCED_TAB}
|
||||
label={i18n.ADVANCED_MENU_ITEM}
|
||||
isSelected={selectedSettingsTab === ADVANCED_TAB}
|
||||
onClick={() => setSelectedSettingsTab(ADVANCED_TAB)}
|
||||
>
|
||||
<EuiIcon type="advancedSettingsApp" size="l" />
|
||||
</EuiKeyPadMenuItem>
|
||||
)}
|
||||
</EuiKeyPadMenu>
|
||||
</EuiPageSidebar>
|
||||
<EuiPageBody paddingSize="none" panelled={true}>
|
||||
|
@ -287,7 +300,6 @@ export const AssistantSettings: React.FC<Props> = React.memo(
|
|||
setUpdatedDefaultAllowReplacement={setUpdatedDefaultAllowReplacement}
|
||||
/>
|
||||
)}
|
||||
{selectedSettingsTab === FUNCTIONS_TAB && <></>}
|
||||
{selectedSettingsTab === ADVANCED_TAB && <AdvancedSettings />}
|
||||
</EuiSplitPanel.Inner>
|
||||
<EuiSplitPanel.Inner
|
||||
|
|
|
@ -49,13 +49,6 @@ export const ANONYMIZATION_MENU_ITEM = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const FUNCTIONS_MENU_ITEM = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.settingsFunctionsMenuItemTitle',
|
||||
{
|
||||
defaultMessage: 'Functions',
|
||||
}
|
||||
);
|
||||
|
||||
export const ADVANCED_MENU_ITEM = i18n.translate(
|
||||
'xpack.elasticAssistant.assistant.settings.settingsAdvancedMenuItemTitle',
|
||||
{
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import type { IToasts } from '@kbn/core-notifications-browser';
|
||||
import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { deleteKnowledgeBase } from '../../assistant/api';
|
||||
import { useInvalidateKnowledgeBaseStatus } from '../use_knowledge_base_status/use_knowledge_base_status';
|
||||
|
||||
const DELETE_KNOWLEDGE_BASE_MUTATION_KEY = ['elastic-assistant', 'delete-knowledge-base'];
|
||||
|
||||
export interface UseDeleteKnowledgeBaseParams {
|
||||
http: HttpSetup;
|
||||
toasts?: IToasts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for deleting the Knowledge Base. Provide a resource name to delete a
|
||||
* specific resource within KB.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {IToasts} [options.toasts] - IToasts
|
||||
*
|
||||
* @returns {useMutation} hook for deleting the Knowledge Base
|
||||
*/
|
||||
export const useDeleteKnowledgeBase = ({ http, toasts }: UseDeleteKnowledgeBaseParams) => {
|
||||
const invalidateKnowledgeBaseStatus = useInvalidateKnowledgeBaseStatus();
|
||||
return useMutation(
|
||||
DELETE_KNOWLEDGE_BASE_MUTATION_KEY,
|
||||
(resource?: string | void) => {
|
||||
// Optional params workaround: see: https://github.com/TanStack/query/issues/1077#issuecomment-1431247266
|
||||
return deleteKnowledgeBase({ http, resource: resource ?? undefined });
|
||||
},
|
||||
{
|
||||
onError: (error: IHttpFetchError<ResponseErrorBody>) => {
|
||||
if (error.name !== 'AbortError') {
|
||||
toasts?.addError(
|
||||
error.body && error.body.message ? new Error(error.body.message) : error,
|
||||
{
|
||||
title: i18n.translate('xpack.elasticAssistant.knowledgeBase.deleteError', {
|
||||
defaultMessage: 'Error deleting Knowledge Base',
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
onSettled: () => {
|
||||
invalidateKnowledgeBaseStatus();
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser';
|
||||
import type { IToasts } from '@kbn/core-notifications-browser';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useCallback } from 'react';
|
||||
import { getKnowledgeBaseStatus } from '../../assistant/api';
|
||||
|
||||
const KNOWLEDGE_BASE_STATUS_QUERY_KEY = ['elastic-assistant', 'knowledge-base-status'];
|
||||
|
||||
export interface UseKnowledgeBaseStatusParams {
|
||||
http: HttpSetup;
|
||||
resource?: string;
|
||||
toasts?: IToasts;
|
||||
}
|
||||
|
||||
export interface GetKnowledgeBaseStatusResponse {
|
||||
elser_exists: boolean;
|
||||
esql_exists?: boolean;
|
||||
index_exists: boolean;
|
||||
pipeline_exists: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for getting the status of the Knowledge Base. Provide a resource name to include
|
||||
* the status for that specific resource within the KB.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {IToasts} [options.toasts] - IToasts
|
||||
*
|
||||
* @returns {useQuery} hook for getting the status of the Knowledge Base
|
||||
*/
|
||||
export const useKnowledgeBaseStatus = ({
|
||||
http,
|
||||
resource,
|
||||
toasts,
|
||||
}: UseKnowledgeBaseStatusParams): UseQueryResult<
|
||||
GetKnowledgeBaseStatusResponse,
|
||||
IHttpFetchError
|
||||
> => {
|
||||
return useQuery(
|
||||
KNOWLEDGE_BASE_STATUS_QUERY_KEY,
|
||||
async ({ signal }) => {
|
||||
return getKnowledgeBaseStatus({ http, resource, signal });
|
||||
},
|
||||
{
|
||||
retry: false,
|
||||
keepPreviousData: true,
|
||||
// Deprecated, hoist to `queryCache` w/in `QueryClient. See: https://stackoverflow.com/a/76961109
|
||||
onError: (error: IHttpFetchError<ResponseErrorBody>) => {
|
||||
if (error.name !== 'AbortError') {
|
||||
toasts?.addError(
|
||||
error.body && error.body.message ? new Error(error.body.message) : error,
|
||||
{
|
||||
title: i18n.translate('xpack.elasticAssistant.knowledgeBase.statusError', {
|
||||
defaultMessage: 'Error fetching Knowledge Base Status',
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this hook to invalidate the Knowledge Base Status cache. For example,
|
||||
* Knowledge Base actions setting up, adding resources, or deleting should lead
|
||||
* to cache invalidation.
|
||||
*
|
||||
* @returns {Function} - Function to invalidate the Knowledge Base Status cache
|
||||
*/
|
||||
export const useInvalidateKnowledgeBaseStatus = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useCallback(() => {
|
||||
queryClient.invalidateQueries(KNOWLEDGE_BASE_STATUS_QUERY_KEY, {
|
||||
refetchType: 'active',
|
||||
});
|
||||
}, [queryClient]);
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser';
|
||||
import type { IToasts } from '@kbn/core-notifications-browser';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { postKnowledgeBase } from '../../assistant/api';
|
||||
import { useInvalidateKnowledgeBaseStatus } from '../use_knowledge_base_status/use_knowledge_base_status';
|
||||
|
||||
const SETUP_KNOWLEDGE_BASE_MUTATION_KEY = ['elastic-assistant', 'post-knowledge-base'];
|
||||
|
||||
export interface UseSetupKnowledgeBaseParams {
|
||||
http: HttpSetup;
|
||||
toasts?: IToasts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for setting up the Knowledge Base. Provide a resource name to set
|
||||
* up a specific part of the KB.
|
||||
*
|
||||
* @param {Object} options - The options object.
|
||||
* @param {HttpSetup} options.http - HttpSetup
|
||||
* @param {IToasts} [options.toasts] - IToasts
|
||||
*
|
||||
* @returns {useMutation} mutation hook for setting up the Knowledge Base
|
||||
*/
|
||||
export const useSetupKnowledgeBase = ({ http, toasts }: UseSetupKnowledgeBaseParams) => {
|
||||
const invalidateKnowledgeBaseStatus = useInvalidateKnowledgeBaseStatus();
|
||||
|
||||
return useMutation(
|
||||
SETUP_KNOWLEDGE_BASE_MUTATION_KEY,
|
||||
(resource?: string | void) => {
|
||||
// Optional params workaround: see: https://github.com/TanStack/query/issues/1077#issuecomment-1431247266
|
||||
return postKnowledgeBase({ http, resource: resource ?? undefined });
|
||||
},
|
||||
{
|
||||
onError: (error: IHttpFetchError<ResponseErrorBody>) => {
|
||||
if (error.name !== 'AbortError') {
|
||||
toasts?.addError(
|
||||
error.body && error.body.message ? new Error(error.body.message) : error,
|
||||
{
|
||||
title: i18n.translate('xpack.elasticAssistant.knowledgeBase.setupError', {
|
||||
defaultMessage: 'Error setting up Knowledge Base',
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
onSettled: () => {
|
||||
invalidateKnowledgeBaseStatus();
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
|
@ -133,3 +133,10 @@ export type { PromptContextTemplate } from './impl/assistant/prompt_context/type
|
|||
* can be displayed when corresponding PromptContext's are registered.
|
||||
*/
|
||||
export type { QuickPrompt } from './impl/assistant/quick_prompts/types';
|
||||
|
||||
/**
|
||||
* Knowledge Base API Responses
|
||||
*/
|
||||
export type { DeleteKnowledgeBaseResponse } from './impl/assistant/api';
|
||||
export type { GetKnowledgeBaseStatusResponse } from './impl/assistant/api';
|
||||
export type { PostKnowledgeBaseResponse } from './impl/assistant/api';
|
||||
|
|
|
@ -7,3 +7,8 @@ This plugin does NOT contain UI components. See `x-pack/packages/kbn-elastic-ass
|
|||
## Maintainers
|
||||
|
||||
Maintained by the Security Solution team
|
||||
|
||||
|
||||
### Testing
|
||||
|
||||
To run the tests for this plugin, run `node scripts/jest --watch x-pack/plugins/elastic_assistant/jest.config.js --coverage` from the Kibana root directory.
|
|
@ -11,3 +11,6 @@ export const PLUGIN_NAME = 'elasticAssistant';
|
|||
export const BASE_PATH = '/internal/elastic_assistant';
|
||||
|
||||
export const POST_ACTIONS_CONNECTOR_EXECUTE = `${BASE_PATH}/actions/connector/{connectorId}/_execute`;
|
||||
|
||||
// Knowledge Base
|
||||
export const KNOWLEDGE_BASE = `${BASE_PATH}/knowledge_base/{resource?}`;
|
||||
|
|
|
@ -5,7 +5,29 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { httpServerMock } from '@kbn/core/server/mocks';
|
||||
import { KNOWLEDGE_BASE } from '../../common/constants';
|
||||
|
||||
export const requestMock = {
|
||||
create: httpServerMock.createKibanaRequest,
|
||||
};
|
||||
|
||||
export const getGetKnowledgeBaseStatusRequest = (resource?: string) =>
|
||||
requestMock.create({
|
||||
method: 'get',
|
||||
path: KNOWLEDGE_BASE,
|
||||
query: { resource },
|
||||
});
|
||||
|
||||
export const getPostKnowledgeBaseRequest = (resource?: string) =>
|
||||
requestMock.create({
|
||||
method: 'post',
|
||||
path: KNOWLEDGE_BASE,
|
||||
query: { resource },
|
||||
});
|
||||
|
||||
export const getDeleteKnowledgeBaseRequest = (resource?: string) =>
|
||||
requestMock.create({
|
||||
method: 'delete',
|
||||
path: KNOWLEDGE_BASE,
|
||||
query: { resource },
|
||||
});
|
||||
|
|
|
@ -4,8 +4,16 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { coreMock } from '@kbn/core/server/mocks';
|
||||
import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
|
||||
import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock';
|
||||
import { MockedKeys } from '@kbn/utility-types-jest';
|
||||
import { AwaitedProperties } from '@kbn/utility-types';
|
||||
import {
|
||||
ElasticAssistantApiRequestHandlerContext,
|
||||
ElasticAssistantRequestHandlerContext,
|
||||
} from '../types';
|
||||
import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server';
|
||||
|
||||
export const createMockClients = () => {
|
||||
const core = coreMock.createRequestHandlerContext();
|
||||
|
@ -14,6 +22,10 @@ export const createMockClients = () => {
|
|||
return {
|
||||
core,
|
||||
clusterClient: core.elasticsearch.client,
|
||||
elasticAssistant: {
|
||||
actions: actionsClientMock.create(),
|
||||
logger: loggingSystemMock.createLogger(),
|
||||
},
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
|
||||
licensing: {
|
||||
|
@ -28,17 +40,39 @@ export const createMockClients = () => {
|
|||
|
||||
type MockClients = ReturnType<typeof createMockClients>;
|
||||
|
||||
const convertRequestContextMock = <T>(context: T) => {
|
||||
return coreMock.createCustomRequestHandlerContext(context);
|
||||
export type ElasticAssistantRequestHandlerContextMock = MockedKeys<
|
||||
AwaitedProperties<Omit<ElasticAssistantRequestHandlerContext, 'resolve'>>
|
||||
> & {
|
||||
core: MockClients['core'];
|
||||
};
|
||||
|
||||
const createMockConfig = () => ({});
|
||||
|
||||
const createAppClientMock = () => ({});
|
||||
|
||||
const createRequestContextMock = (clients: MockClients = createMockClients()) => {
|
||||
const createRequestContextMock = (
|
||||
clients: MockClients = createMockClients()
|
||||
): ElasticAssistantRequestHandlerContextMock => {
|
||||
return {
|
||||
core: clients.core,
|
||||
elasticAssistant: createElasticAssistantRequestContextMock(clients),
|
||||
};
|
||||
};
|
||||
|
||||
const convertRequestContextMock = (
|
||||
context: AwaitedProperties<ElasticAssistantRequestHandlerContextMock>
|
||||
): ElasticAssistantRequestHandlerContext => {
|
||||
return coreMock.createCustomRequestHandlerContext(
|
||||
context
|
||||
) as unknown as ElasticAssistantRequestHandlerContext;
|
||||
};
|
||||
|
||||
const createElasticAssistantRequestContextMock = (
|
||||
clients: MockClients
|
||||
): jest.Mocked<ElasticAssistantApiRequestHandlerContext> => {
|
||||
return {
|
||||
actions: clients.elasticAssistant.actions as unknown as ActionsPluginStart,
|
||||
logger: clients.elasticAssistant.logger,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ const buildResponses = (method: Method, calls: MockCall[]): ResponseCall[] => {
|
|||
case 'custom':
|
||||
return calls.map(([call]) => ({
|
||||
status: call.statusCode,
|
||||
body: JSON.parse(call.body),
|
||||
body:
|
||||
Buffer.isBuffer(call.body) || typeof call.body === 'string'
|
||||
? JSON.parse(call.body)
|
||||
: call.body,
|
||||
}));
|
||||
case 'customError':
|
||||
return calls.map(([call]) => ({
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
### Knowledge Base Assets
|
||||
|
||||
This directory contains assets for the Knowledge Base feature. The assets are used by the Elastic AI Assistant to answer questions about content that the underlying model may not have been trained on. Initial assets are provided for the following categories:
|
||||
|
||||
* ES|QL
|
||||
* General Documentation as from: https://github.com/elastic/elasticsearch/tree/main/docs/reference/esql
|
||||
* Excluding `functions/signature/*.svg`
|
||||
* ANTLR Language Definitions as from: https://github.com/elastic/elasticsearch/tree/main/x-pack/plugin/esql/src/main/antlr
|
||||
|
||||
The assets are stored in their original source format, so `.asciidoc` for documentation, and `.g4` and `.tokens` for the ANTLR language definitions. File names have been updated to be snake_case to satisfy Kibana linting rules.
|
||||
|
||||
### Future
|
||||
|
||||
Once asset format and chunking strategies are finalized, we may want to either move the assets to a shared package so they can be consumed by other plugins, or potentially ship the pre-packaged ELSER embeddings as part of a Fleet Integration. For now though, the assets will be included in their source format within the plugin, and can then be processed and embedded at runtime.
|
|
@ -0,0 +1,30 @@
|
|||
[[esql-agg-functions]]
|
||||
== {esql} aggregation functions
|
||||
|
||||
++++
|
||||
<titleabbrev>Aggregation functions</titleabbrev>
|
||||
++++
|
||||
|
||||
<<esql-stats-by>> support these functions:
|
||||
|
||||
// tag::functions[]
|
||||
* <<esql-agg-avg>>
|
||||
* <<esql-agg-count>>
|
||||
* <<esql-agg-count-distinct>>
|
||||
* <<esql-agg-max>>
|
||||
* <<esql-agg-median>>
|
||||
* <<esql-agg-median-absolute-deviation>>
|
||||
* <<esql-agg-min>>
|
||||
* <<esql-agg-percentile>>
|
||||
* <<esql-agg-sum>>
|
||||
// end::functions[]
|
||||
|
||||
include::aggregation-functions/avg.asciidoc[]
|
||||
include::aggregation-functions/count.asciidoc[]
|
||||
include::aggregation-functions/count-distinct.asciidoc[]
|
||||
include::aggregation-functions/max.asciidoc[]
|
||||
include::aggregation-functions/median.asciidoc[]
|
||||
include::aggregation-functions/median-absolute-deviation.asciidoc[]
|
||||
include::aggregation-functions/min.asciidoc[]
|
||||
include::aggregation-functions/percentile.asciidoc[]
|
||||
include::aggregation-functions/sum.asciidoc[]
|
|
@ -0,0 +1,14 @@
|
|||
[[esql-agg-avg]]
|
||||
=== `AVG`
|
||||
The average of a numeric field.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats.csv-spec[tag=avg]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats.csv-spec[tag=avg-result]
|
||||
|===
|
||||
|
||||
The result is always a `double` not matter the input type.
|
|
@ -0,0 +1,18 @@
|
|||
[[esql-agg-count]]
|
||||
=== `COUNT`
|
||||
Counts field values.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats.csv-spec[tag=count]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats.csv-spec[tag=count-result]
|
||||
|===
|
||||
|
||||
Can take any field type as input and the result is always a `long` not matter
|
||||
the input type.
|
||||
|
||||
NOTE: There isn't yet a `COUNT(*)`. Please count a single valued field if you
|
||||
need a count of rows.
|
|
@ -0,0 +1,43 @@
|
|||
[[esql-agg-count-distinct]]
|
||||
=== `COUNT_DISTINCT`
|
||||
The approximate number of distinct values.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct-result]
|
||||
|===
|
||||
|
||||
Can take any field type as input and the result is always a `long` not matter
|
||||
the input type.
|
||||
|
||||
==== Counts are approximate
|
||||
|
||||
Computing exact counts requires loading values into a set and returning its
|
||||
size. This doesn't scale when working on high-cardinality sets and/or large
|
||||
values as the required memory usage and the need to communicate those
|
||||
per-shard sets between nodes would utilize too many resources of the cluster.
|
||||
|
||||
This `COUNT_DISTINCT` function is based on the
|
||||
https://static.googleusercontent.com/media/research.google.com/fr//pubs/archive/40671.pdf[HyperLogLog++]
|
||||
algorithm, which counts based on the hashes of the values with some interesting
|
||||
properties:
|
||||
|
||||
include::../../aggregations/metrics/cardinality-aggregation.asciidoc[tag=explanation]
|
||||
|
||||
==== Precision is configurable
|
||||
|
||||
The `COUNT_DISTINCT` function takes an optional second parameter to configure the
|
||||
precision discussed previously.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct-precision]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct-precision-result]
|
||||
|===
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-agg-max]]
|
||||
=== `MAX`
|
||||
The maximum value of a numeric field.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats.csv-spec[tag=max]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats.csv-spec[tag=max-result]
|
||||
|===
|
|
@ -0,0 +1,21 @@
|
|||
[[esql-agg-median]]
|
||||
=== `MEDIAN`
|
||||
The value that is greater than half of all values and less than half of
|
||||
all values, also known as the 50% <<esql-agg-percentile>>.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=median]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=median-result]
|
||||
|===
|
||||
|
||||
NOTE: Like <<esql-agg-percentile>>, `MEDIAN` is <<esql-agg-percentile-approximate,usually approximate>>.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
`MEDIAN` is also {wikipedia}/Nondeterministic_algorithm[non-deterministic].
|
||||
This means you can get slightly different results using the same data.
|
||||
====
|
|
@ -0,0 +1,28 @@
|
|||
[[esql-agg-median-absolute-deviation]]
|
||||
=== `MEDIAN_ABSOLUTE_DEVIATION`
|
||||
The median absolute deviation, a measure of variability. It is a robust
|
||||
statistic, meaning that it is useful for describing data that may have outliers,
|
||||
or may not be normally distributed. For such data it can be more descriptive than
|
||||
standard deviation.
|
||||
|
||||
It is calculated as the median of each data point’s deviation from the median of
|
||||
the entire sample. That is, for a random variable `X`, the median absolute deviation
|
||||
is `median(|median(X) - Xi|)`.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=median-absolute-deviation]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=median-absolute-deviation-result]
|
||||
|===
|
||||
|
||||
NOTE: Like <<esql-agg-percentile>>, `MEDIAN_ABSOLUTE_DEVIATION` is
|
||||
<<esql-agg-percentile-approximate,usually approximate>>.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
`MEDIAN_ABSOLUTE_DEVIATION` is also {wikipedia}/Nondeterministic_algorithm[non-deterministic].
|
||||
This means you can get slightly different results using the same data.
|
||||
====
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-agg-min]]
|
||||
=== `MIN`
|
||||
The minimum value of a numeric field.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats.csv-spec[tag=min]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats.csv-spec[tag=min-result]
|
||||
|===
|
|
@ -0,0 +1,28 @@
|
|||
[[esql-agg-percentile]]
|
||||
=== `PERCENTILE`
|
||||
The value at which a certain percentage of observed values occur. For example,
|
||||
the 95th percentile is the value which is greater than 95% of the observed values and
|
||||
the 50th percentile is the <<esql-agg-median>>.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=percentile]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats_percentile.csv-spec[tag=percentile-result]
|
||||
|===
|
||||
|
||||
[[esql-agg-percentile-approximate]]
|
||||
==== `PERCENTILE` is (usually) approximate
|
||||
|
||||
include::../../aggregations/metrics/percentile-aggregation.asciidoc[tag=approximate]
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
`PERCENTILE` is also {wikipedia}/Nondeterministic_algorithm[non-deterministic].
|
||||
This means you can get slightly different results using the same data.
|
||||
====
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-agg-sum]]
|
||||
=== `SUM`
|
||||
The sum of a numeric field.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/stats.csv-spec[tag=sum]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/stats.csv-spec[tag=sum-result]
|
||||
|===
|
|
@ -0,0 +1,134 @@
|
|||
[[esql-functions]]
|
||||
== {esql} functions
|
||||
|
||||
++++
|
||||
<titleabbrev>Functions</titleabbrev>
|
||||
++++
|
||||
|
||||
<<esql-row,`ROW`>>, <<esql-eval,`EVAL`>> and <<esql-where,`WHERE`>> support
|
||||
these functions:
|
||||
|
||||
* <<esql-abs>>
|
||||
* <<esql-acos>>
|
||||
* <<esql-asin>>
|
||||
* <<esql-atan>>
|
||||
* <<esql-atan2>>
|
||||
* <<esql-auto_bucket>>
|
||||
* <<esql-case>>
|
||||
* <<esql-ceil>>
|
||||
* <<esql-cidr_match>>
|
||||
* <<esql-coalesce>>
|
||||
* <<esql-concat>>
|
||||
* <<esql-cos>>
|
||||
* <<esql-cosh>>
|
||||
* <<esql-date_extract>>
|
||||
* <<esql-date_format>>
|
||||
* <<esql-date_parse>>
|
||||
* <<esql-date_trunc>>
|
||||
* <<esql-e>>
|
||||
* <<esql-floor>>
|
||||
* <<esql-greatest>>
|
||||
* <<esql-is_finite>>
|
||||
* <<esql-is_infinite>>
|
||||
* <<esql-is_nan>>
|
||||
* <<esql-least>>
|
||||
* <<esql-length>>
|
||||
* <<esql-log10>>
|
||||
* <<esql-ltrim>>
|
||||
* <<esql-rtrim>>
|
||||
* <<esql-mv_avg>>
|
||||
* <<esql-mv_concat>>
|
||||
* <<esql-mv_count>>
|
||||
* <<esql-mv_dedupe>>
|
||||
* <<esql-mv_max>>
|
||||
* <<esql-mv_median>>
|
||||
* <<esql-mv_min>>
|
||||
* <<esql-mv_sum>>
|
||||
* <<esql-now>>
|
||||
* <<esql-pi>>
|
||||
* <<esql-pow>>
|
||||
* <<esql-round>>
|
||||
* <<esql-sin>>
|
||||
* <<esql-sinh>>
|
||||
* <<esql-split>>
|
||||
* <<esql-starts_with>>
|
||||
* <<esql-substring>>
|
||||
* <<esql-left>>
|
||||
* <<esql-tan>>
|
||||
* <<esql-tanh>>
|
||||
* <<esql-tau>>
|
||||
* <<esql-to_boolean>>
|
||||
* <<esql-to_datetime>>
|
||||
* <<esql-to_degrees>>
|
||||
* <<esql-to_double>>
|
||||
* <<esql-to_integer>>
|
||||
* <<esql-to_ip>>
|
||||
* <<esql-to_long>>
|
||||
* <<esql-to_radians>>
|
||||
* <<esql-to_string>>
|
||||
* <<esql-to_unsigned_long>>
|
||||
* <<esql-to_version>>
|
||||
* <<esql-trim>>
|
||||
|
||||
include::functions/abs.asciidoc[]
|
||||
include::functions/acos.asciidoc[]
|
||||
include::functions/asin.asciidoc[]
|
||||
include::functions/atan.asciidoc[]
|
||||
include::functions/atan2.asciidoc[]
|
||||
include::functions/auto_bucket.asciidoc[]
|
||||
include::functions/case.asciidoc[]
|
||||
include::functions/ceil.asciidoc[]
|
||||
include::functions/cidr_match.asciidoc[]
|
||||
include::functions/coalesce.asciidoc[]
|
||||
include::functions/concat.asciidoc[]
|
||||
include::functions/cos.asciidoc[]
|
||||
include::functions/cosh.asciidoc[]
|
||||
include::functions/date_extract.asciidoc[]
|
||||
include::functions/date_format.asciidoc[]
|
||||
include::functions/date_parse.asciidoc[]
|
||||
include::functions/date_trunc.asciidoc[]
|
||||
include::functions/e.asciidoc[]
|
||||
include::functions/floor.asciidoc[]
|
||||
include::functions/greatest.asciidoc[]
|
||||
include::functions/is_finite.asciidoc[]
|
||||
include::functions/is_infinite.asciidoc[]
|
||||
include::functions/is_nan.asciidoc[]
|
||||
include::functions/least.asciidoc[]
|
||||
include::functions/length.asciidoc[]
|
||||
include::functions/log10.asciidoc[]
|
||||
include::functions/ltrim.asciidoc[]
|
||||
include::functions/rtrim.asciidoc[]
|
||||
include::functions/mv_avg.asciidoc[]
|
||||
include::functions/mv_concat.asciidoc[]
|
||||
include::functions/mv_count.asciidoc[]
|
||||
include::functions/mv_dedupe.asciidoc[]
|
||||
include::functions/mv_max.asciidoc[]
|
||||
include::functions/mv_median.asciidoc[]
|
||||
include::functions/mv_min.asciidoc[]
|
||||
include::functions/mv_sum.asciidoc[]
|
||||
include::functions/now.asciidoc[]
|
||||
include::functions/pi.asciidoc[]
|
||||
include::functions/pow.asciidoc[]
|
||||
include::functions/round.asciidoc[]
|
||||
include::functions/sin.asciidoc[]
|
||||
include::functions/sinh.asciidoc[]
|
||||
include::functions/split.asciidoc[]
|
||||
include::functions/sqrt.asciidoc[]
|
||||
include::functions/starts_with.asciidoc[]
|
||||
include::functions/substring.asciidoc[]
|
||||
include::functions/left.asciidoc[]
|
||||
include::functions/tan.asciidoc[]
|
||||
include::functions/tanh.asciidoc[]
|
||||
include::functions/tau.asciidoc[]
|
||||
include::functions/to_boolean.asciidoc[]
|
||||
include::functions/to_datetime.asciidoc[]
|
||||
include::functions/to_degrees.asciidoc[]
|
||||
include::functions/to_double.asciidoc[]
|
||||
include::functions/to_integer.asciidoc[]
|
||||
include::functions/to_ip.asciidoc[]
|
||||
include::functions/to_long.asciidoc[]
|
||||
include::functions/to_radians.asciidoc[]
|
||||
include::functions/to_string.asciidoc[]
|
||||
include::functions/to_unsigned_long.asciidoc[]
|
||||
include::functions/to_version.asciidoc[]
|
||||
include::functions/trim.asciidoc[]
|
|
@ -0,0 +1,39 @@
|
|||
[[esql-processing-commands]]
|
||||
== {esql} processing commands
|
||||
|
||||
++++
|
||||
<titleabbrev>Processing commands</titleabbrev>
|
||||
++++
|
||||
|
||||
{esql} processing commands change an input table by adding, removing, or changing
|
||||
rows and columns.
|
||||
|
||||
image::images/esql/processing-command.svg[A processing command changing an input table,align="center"]
|
||||
|
||||
{esql} supports these processing commands:
|
||||
|
||||
* <<esql-dissect>>
|
||||
* <<esql-drop>>
|
||||
* <<esql-enrich>>
|
||||
* <<esql-eval>>
|
||||
* <<esql-grok>>
|
||||
* <<esql-keep>>
|
||||
* <<esql-limit>>
|
||||
* <<esql-mv_expand>>
|
||||
* <<esql-rename>>
|
||||
* <<esql-sort>>
|
||||
* <<esql-stats-by>>
|
||||
* <<esql-where>>
|
||||
|
||||
include::processing-commands/dissect.asciidoc[]
|
||||
include::processing-commands/drop.asciidoc[]
|
||||
include::processing-commands/enrich.asciidoc[]
|
||||
include::processing-commands/eval.asciidoc[]
|
||||
include::processing-commands/grok.asciidoc[]
|
||||
include::processing-commands/keep.asciidoc[]
|
||||
include::processing-commands/limit.asciidoc[]
|
||||
include::processing-commands/mv_expand.asciidoc[]
|
||||
include::processing-commands/rename.asciidoc[]
|
||||
include::processing-commands/sort.asciidoc[]
|
||||
include::processing-commands/stats.asciidoc[]
|
||||
include::processing-commands/where.asciidoc[]
|
|
@ -0,0 +1,20 @@
|
|||
[[esql-source-commands]]
|
||||
== {esql} source commands
|
||||
|
||||
++++
|
||||
<titleabbrev>Source commands</titleabbrev>
|
||||
++++
|
||||
|
||||
An {esql} source command produces a table, typically with data from {es}.
|
||||
|
||||
image::images/esql/source-command.svg[A source command producing a table from {es},align="center"]
|
||||
|
||||
{esql} supports these source commands:
|
||||
|
||||
* <<esql-from>>
|
||||
* <<esql-row>>
|
||||
* <<esql-show>>
|
||||
|
||||
include::source-commands/from.asciidoc[]
|
||||
include::source-commands/row.asciidoc[]
|
||||
include::source-commands/show.asciidoc[]
|
|
@ -0,0 +1,162 @@
|
|||
[[esql-syntax]]
|
||||
== {esql} syntax reference
|
||||
|
||||
++++
|
||||
<titleabbrev>Syntax reference</titleabbrev>
|
||||
++++
|
||||
|
||||
[discrete]
|
||||
[[esql-basic-syntax]]
|
||||
=== Basic syntax
|
||||
|
||||
An {esql} query is composed of a <<esql-source-commands,source command>> followed
|
||||
by an optional series of <<esql-processing-commands,processing commands>>,
|
||||
separated by a pipe character: `|`. For example:
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
source-command
|
||||
| processing-command1
|
||||
| processing-command2
|
||||
----
|
||||
|
||||
The result of a query is the table produced by the final processing command.
|
||||
|
||||
For readability, this documentation puts each processing command on a new line.
|
||||
However, you can write an {esql} query as a single line. The following query is
|
||||
identical to the previous one:
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
source-command | processing-command1 | processing-command2
|
||||
----
|
||||
|
||||
[discrete]
|
||||
[[esql-comments]]
|
||||
=== Comments
|
||||
{esql} uses C++ style comments:
|
||||
|
||||
* double slash `//` for single line comments
|
||||
* `/*` and `*/` for block comments
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
// Query the employees index
|
||||
FROM employees
|
||||
| WHERE height > 2
|
||||
----
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM /* Query the employees index */ employees
|
||||
| WHERE height > 2
|
||||
----
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
/* Query the
|
||||
* employees
|
||||
* index */
|
||||
| WHERE height > 2
|
||||
----
|
||||
|
||||
[discrete]
|
||||
[[esql-operators]]
|
||||
=== Operators
|
||||
These binary comparison operators are supported:
|
||||
|
||||
* equality: `==`
|
||||
* inequality: `!=`
|
||||
* less than: `<`
|
||||
* less than or equal: `<=`
|
||||
* larger than: `>`
|
||||
* larger than or equal: `>=`
|
||||
|
||||
The `IN` operator allows testing whether a field or expression equals
|
||||
an element in a list of literals, fields or expressions:
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
include::{esql-specs}/row.csv-spec[tag=in-with-expressions]
|
||||
----
|
||||
|
||||
For string comparison using wildcards or regular expressions, use `LIKE` or
|
||||
`RLIKE`:
|
||||
|
||||
* Use `LIKE` to match strings using wildcards. The following wildcard characters
|
||||
are supported:
|
||||
+
|
||||
--
|
||||
** `*` matches zero or more characters.
|
||||
** `?` matches one character.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| WHERE first_name LIKE "?b*"
|
||||
| KEEP first_name, last_name
|
||||
----
|
||||
--
|
||||
|
||||
* Use `RLIKE` to match strings using <<regexp-syntax,regular expressions>>:
|
||||
+
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| WHERE first_name RLIKE ".leja.*"
|
||||
| KEEP first_name, last_name
|
||||
----
|
||||
|
||||
The following boolean operators are supported:
|
||||
|
||||
* `AND`
|
||||
* `OR`
|
||||
* `NOT`
|
||||
|
||||
[discrete]
|
||||
[[esql-predicates]]
|
||||
=== Predicates
|
||||
|
||||
For NULL comparison use the `IS NULL` and `IS NOT NULL` predicates:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/null.csv-spec[tag=is-null]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/null.csv-spec[tag=is-null-result]
|
||||
|===
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/null.csv-spec[tag=is-not-null]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/null.csv-spec[tag=is-not-null-result]
|
||||
|===
|
||||
|
||||
[discrete]
|
||||
[[esql-timespan-literals]]
|
||||
=== Timespan literals
|
||||
|
||||
Datetime intervals and timespans can be expressed using timespan literals.
|
||||
Timespan literals are a combination of a number and a qualifier. These
|
||||
qualifiers are supported:
|
||||
|
||||
* `millisecond`/`milliseconds`
|
||||
* `second`/`seconds`
|
||||
* `minute`/`minutes`
|
||||
* `hour`/`hours`
|
||||
* `day`/`days`
|
||||
* `week`/`weeks`
|
||||
* `month`/`months`
|
||||
* `year`/`years`
|
||||
|
||||
Timespan literals are not whitespace sensitive. These expressions are all valid:
|
||||
|
||||
* `1day`
|
||||
* `1 day`
|
||||
* `1 day`
|
|
@ -0,0 +1,17 @@
|
|||
[[esql-abs]]
|
||||
=== `ABS`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/abs.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the absolute value.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| KEEP first_name, last_name, height
|
||||
| EVAL abs_height = ABS(0.0 - height)
|
||||
----
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/abs.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-acos]]
|
||||
=== `ACOS`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/acos.svg[Embedded,opts=inline]
|
||||
|
||||
Inverse https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[cosine] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=acos]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=acos-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/acos.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-asin]]
|
||||
=== `ASIN`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/asin.svg[Embedded,opts=inline]
|
||||
|
||||
Inverse https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[sine] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=asin]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=asin-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/asin.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-atan]]
|
||||
=== `ATAN`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/atan.svg[Embedded,opts=inline]
|
||||
|
||||
Inverse https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[tangent] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=atan]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=atan-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/atan.asciidoc[]
|
|
@ -0,0 +1,20 @@
|
|||
[[esql-atan2]]
|
||||
=== `ATAN2`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/atan2.svg[Embedded,opts=inline]
|
||||
|
||||
The https://en.wikipedia.org/wiki/Atan2[angle] between the positive x-axis and the
|
||||
ray from the origin to the point (x , y) in the Cartesian plane.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=atan2]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=atan2-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/atan2.asciidoc[]
|
|
@ -0,0 +1,71 @@
|
|||
[[esql-auto_bucket]]
|
||||
=== `AUTO_BUCKET`
|
||||
Creates human-friendly buckets and returns a `datetime` value for each row that
|
||||
corresponds to the resulting bucket the row falls into. Combine `AUTO_BUCKET`
|
||||
with <<esql-stats-by>> to create a date histogram.
|
||||
|
||||
You provide a target number of buckets, a start date, and an end date, and it
|
||||
picks an appropriate bucket size to generate the target number of buckets or
|
||||
fewer. For example, this asks for at most 20 buckets over a whole year, which
|
||||
picks monthly buckets:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_month]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_month-result]
|
||||
|===
|
||||
|
||||
The goal isn't to provide *exactly* the target number of buckets, it's to pick a
|
||||
range that people are comfortable with that provides at most the target number of
|
||||
buckets.
|
||||
|
||||
If you ask for more buckets then `AUTO_BUCKET` can pick a smaller range. For example,
|
||||
asking for at most 100 buckets in a year will get you week long buckets:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_week]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_week-result]
|
||||
|===
|
||||
|
||||
`AUTO_BUCKET` does not filter any rows. It only uses the provided time range to
|
||||
pick a good bucket size. For rows with a date outside of the range, it returns a
|
||||
`datetime` that corresponds to a bucket outside the range. Combine `AUTO_BUCKET`
|
||||
with <<esql-where>> to filter rows.
|
||||
|
||||
A more complete example might look like:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg-result]
|
||||
|===
|
||||
|
||||
NOTE: `AUTO_BUCKET` does not create buckets that don't match any documents. That's
|
||||
why the example above is missing `1985-02-01` and other dates.
|
||||
|
||||
==== Numeric fields
|
||||
|
||||
`auto_bucket` can also operate on numeric fields like this:
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/ints.csv-spec[tag=auto_bucket]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/ints.csv-spec[tag=auto_bucket-result]
|
||||
|===
|
||||
|
||||
Unlike the example above where you are intentionally filtering on a date range,
|
||||
you rarely want to filter on a numeric range. So you have find the `min` and `max`
|
||||
separately. We don't yet have an easy way to do that automatically. Improvements
|
||||
coming!
|
|
@ -0,0 +1,17 @@
|
|||
[[esql-case]]
|
||||
=== `CASE`
|
||||
|
||||
Accepts pairs of conditions and values. The function returns the value that
|
||||
belongs to the first condition that evaluates to `true`. If the number of
|
||||
arguments is odd, the last argument is the default value which is returned when
|
||||
no condition matches.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| EVAL type = CASE(
|
||||
languages <= 1, "monolingual",
|
||||
languages <= 2, "bilingual",
|
||||
"polyglot")
|
||||
| KEEP first_name, last_name, type
|
||||
----
|
|
@ -0,0 +1,23 @@
|
|||
[[esql-ceil]]
|
||||
=== `CEIL`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/floor.svg[Embedded,opts=inline]
|
||||
|
||||
Round a number up to the nearest integer.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=ceil]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=ceil-result]
|
||||
|===
|
||||
|
||||
NOTE: This is a noop for `long` (including unsigned) and `integer`.
|
||||
For `double` this picks the the closest `double` value to the integer ala
|
||||
{javadoc}/java.base/java/lang/Math.html#ceil(double)[Math.ceil].
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/ceil.asciidoc[]
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-cidr_match]]
|
||||
=== `CIDR_MATCH`
|
||||
|
||||
Returns `true` if the provided IP is contained in one of the provided CIDR
|
||||
blocks.
|
||||
|
||||
`CIDR_MATCH` accepts two or more arguments. The first argument is the IP
|
||||
address of type `ip` (both IPv4 and IPv6 are supported). Subsequent arguments
|
||||
are the CIDR blocks to test the IP against.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM hosts
|
||||
| WHERE CIDR_MATCH(ip, "127.0.0.2/32", "127.0.0.3/32")
|
||||
----
|
|
@ -0,0 +1,13 @@
|
|||
[[esql-coalesce]]
|
||||
=== `COALESCE`
|
||||
|
||||
Returns the first non-null value.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/null.csv-spec[tag=coalesce]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/null.csv-spec[tag=coalesce-result]
|
||||
|===
|
|
@ -0,0 +1,10 @@
|
|||
[[esql-concat]]
|
||||
=== `CONCAT`
|
||||
Concatenates two or more strings.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| KEEP first_name, last_name, height
|
||||
| EVAL fullname = CONCAT(first_name, " ", last_name)
|
||||
----
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-cos]]
|
||||
=== `COS`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/cos.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Sine_and_cosine[Cosine] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=cos]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=cos-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/cos.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-cosh]]
|
||||
=== `COSH`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/cosh.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Hyperbolic_functions[Cosine] hyperbolic function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=cosh]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=cosh-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/cosh.asciidoc[]
|
|
@ -0,0 +1,14 @@
|
|||
[[esql-date_extract]]
|
||||
=== `DATE_EXTRACT`
|
||||
Extracts parts of a date, like year, month, day, hour.
|
||||
The supported field types are those provided by https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoField.html[java.time.temporal.ChronoField]
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=dateExtract]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=dateExtract-result]
|
||||
|===
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[[esql-date_format]]
|
||||
=== `DATE_FORMAT`
|
||||
Returns a string representation of a date in the provided format. If no format
|
||||
is specified, the `yyyy-MM-dd'T'HH:mm:ss.SSSZ` format is used.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| KEEP first_name, last_name, hire_date
|
||||
| EVAL hired = DATE_FORMAT(hire_date, "YYYY-MM-dd")
|
||||
----
|
|
@ -0,0 +1,9 @@
|
|||
[[esql-date_parse]]
|
||||
=== `DATE_PARSE`
|
||||
Converts a string to a date, in the provided format. If no format
|
||||
is specified, the `yyyy-MM-dd'T'HH:mm:ss.SSSZ` format is used.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=dateParse]
|
||||
----
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-date_trunc]]
|
||||
=== `DATE_TRUNC`
|
||||
Rounds down a date to the closest interval. Intervals can be expressed using the
|
||||
<<esql-timespan-literals,timespan literal syntax>>.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| EVAL year_hired = DATE_TRUNC(1 year, hire_date)
|
||||
| STATS count(emp_no) BY year_hired
|
||||
| SORT year_hired
|
||||
----
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-e]]
|
||||
=== `E`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/e.svg[Embedded,opts=inline]
|
||||
|
||||
{wikipedia}/E_(mathematical_constant)[Euler's number].
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=e]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=e-result]
|
||||
|===
|
|
@ -0,0 +1,23 @@
|
|||
[[esql-floor]]
|
||||
=== `FLOOR`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/floor.svg[Embedded,opts=inline]
|
||||
|
||||
Round a number down to the nearest integer.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=floor]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=floor-result]
|
||||
|===
|
||||
|
||||
NOTE: This is a noop for `long` (including unsigned) and `integer`.
|
||||
For `double` this picks the the closest `double` value to the integer ala
|
||||
{javadoc}/java.base/java/lang/Math.html#floor(double)[Math.floor].
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/floor.asciidoc[]
|
|
@ -0,0 +1,24 @@
|
|||
[[esql-greatest]]
|
||||
=== `GREATEST`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/greatest.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the maximum value from many columns. This is similar to <<esql-mv_max>>
|
||||
except it's intended to run on multiple columns at once.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=greatest]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=greatest-result]
|
||||
|===
|
||||
|
||||
NOTE: When run on `keyword` or `text` fields, this'll return the last string
|
||||
in alphabetical order. When run on `boolean` columns this will return
|
||||
`true` if any values are `true`.
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/greatest.asciidoc[]
|
|
@ -0,0 +1,9 @@
|
|||
[[esql-is_finite]]
|
||||
=== `IS_FINITE`
|
||||
Returns a boolean that indicates whether its input is a finite number.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
ROW d = 1.0
|
||||
| EVAL s = IS_FINITE(d/0)
|
||||
----
|
|
@ -0,0 +1,9 @@
|
|||
[[esql-is_infinite]]
|
||||
=== `IS_INFINITE`
|
||||
Returns a boolean that indicates whether its input is infinite.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
ROW d = 1.0
|
||||
| EVAL s = IS_INFINITE(d/0)
|
||||
----
|
|
@ -0,0 +1,9 @@
|
|||
[[esql-is_nan]]
|
||||
=== `IS_NAN`
|
||||
Returns a boolean that indicates whether its input is not a number.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
ROW d = 1.0
|
||||
| EVAL s = IS_NAN(d)
|
||||
----
|
|
@ -0,0 +1,24 @@
|
|||
[[esql-least]]
|
||||
=== `LEAST`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/least.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the minimum value from many columns. This is similar to <<esql-mv_min>>
|
||||
except it's intended to run on multiple columns at once.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=least]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=least-result]
|
||||
|===
|
||||
|
||||
NOTE: When run on `keyword` or `text` fields, this'll return the first string
|
||||
in alphabetical order. When run on `boolean` columns this will return
|
||||
`false` if any values are `false`.
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/least.asciidoc[]
|
|
@ -0,0 +1,14 @@
|
|||
[[esql-left]]
|
||||
=== `LEFT`
|
||||
|
||||
Return the substring that extract 'length' chars
|
||||
from string starting from 0.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=left]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=left-result]
|
||||
|===
|
|
@ -0,0 +1,10 @@
|
|||
[[esql-length]]
|
||||
=== `LENGTH`
|
||||
Returns the character length of a string.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
FROM employees
|
||||
| KEEP first_name, last_name, height
|
||||
| EVAL fn_length = LENGTH(first_name)
|
||||
----
|
|
@ -0,0 +1,22 @@
|
|||
[[esql-log10]]
|
||||
=== `LOG10`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/log10.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the log base 10. The input can be any numeric value, the return value
|
||||
is always a double.
|
||||
|
||||
Logs of negative numbers are NaN. Logs of infinites are infinite, as is the log of 0.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=log10]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=log10-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/log10.asciidoc[]
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-ltrim]]
|
||||
=== `LTRIM`
|
||||
Removes leading whitespaces from strings.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=ltrim]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=ltrim-result]
|
||||
|===
|
|
@ -0,0 +1,16 @@
|
|||
[[esql-mv_avg]]
|
||||
=== `MV_AVG`
|
||||
Converts a multivalued field into a single valued field containing the average
|
||||
of all of the values. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_avg]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_avg-result]
|
||||
|===
|
||||
|
||||
|
||||
NOTE: The output type is always a `double` and the input type can be any number.
|
|
@ -0,0 +1,25 @@
|
|||
[[esql-mv_concat]]
|
||||
=== `MV_CONCAT`
|
||||
Converts a multivalued string field into a single valued field containing the
|
||||
concatenation of all values separated by a delimiter:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_concat]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_concat-result]
|
||||
|===
|
||||
|
||||
If you want to concat non-string fields call <<esql-to_string>> on them first:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_concat-to_string]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_concat-to_string-result]
|
||||
|===
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-mv_count]]
|
||||
=== `MV_COUNT`
|
||||
Converts a multivalued field into a single valued field containing a count of the number
|
||||
of values:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_count]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_count-result]
|
||||
|===
|
||||
|
||||
NOTE: This function accepts all types and always returns an `integer`.
|
|
@ -0,0 +1,14 @@
|
|||
[[esql-mv_dedupe]]
|
||||
=== `MV_DEDUPE`
|
||||
Removes duplicates from a multivalued field. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_dedupe]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_dedupe-result]
|
||||
|===
|
||||
|
||||
NOTE: `MV_DEDUPE` may, but won't always, sort the values in the field.
|
|
@ -0,0 +1,24 @@
|
|||
[[esql-mv_max]]
|
||||
=== `MV_MAX`
|
||||
Converts a multivalued field into a single valued field containing the maximum value. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_max]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_max-result]
|
||||
|===
|
||||
|
||||
It can be used by any field type, including `keyword` fields. In that case picks the
|
||||
last string, comparing their utf-8 representation byte by byte:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_max]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_max-result]
|
||||
|===
|
|
@ -0,0 +1,26 @@
|
|||
[[esql-mv_median]]
|
||||
=== `MV_MEDIAN`
|
||||
Converts a multivalued field into a single valued field containing the median value. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_median]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_median-result]
|
||||
|===
|
||||
|
||||
It can be used by any numeric field type and returns a value of the same type. If the
|
||||
row has an even number of values for a column the result will be the average of the
|
||||
middle two entries. If the field is not floating point then the average rounds *down*:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_median_round_down]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_median_round_down-result]
|
||||
|===
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
[[esql-mv_min]]
|
||||
=== `MV_MIN`
|
||||
Converts a multivalued field into a single valued field containing the minimum value. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_min]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_min-result]
|
||||
|===
|
||||
|
||||
It can be used by any field type, including `keyword` fields. In that case picks the
|
||||
first string, comparing their utf-8 representation byte by byte:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_min]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=mv_min-result]
|
||||
|===
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-mv_sum]]
|
||||
=== `MV_SUM`
|
||||
Converts a multivalued field into a single valued field containing the sum
|
||||
of all of the values. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_sum]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=mv_sum-result]
|
||||
|===
|
||||
|
||||
NOTE: The input type can be any number and the output type is the same as the input type.
|
|
@ -0,0 +1,8 @@
|
|||
[[esql-now]]
|
||||
=== `NOW`
|
||||
Returns current date and time.
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
ROW current_date = NOW()
|
||||
----
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-pi]]
|
||||
=== `PI`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/pi.svg[Embedded,opts=inline]
|
||||
|
||||
The {wikipedia}/Pi[ratio] of a circle's circumference to its diameter.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=pi]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=pi-result]
|
||||
|===
|
|
@ -0,0 +1,91 @@
|
|||
[[esql-pow]]
|
||||
=== `POW`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/pow.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the value of a base (first argument) raised to the power of an exponent (second argument).
|
||||
Both arguments must be numeric.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=powDI]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=powDI-result]
|
||||
|===
|
||||
|
||||
==== Type rules
|
||||
|
||||
The type of the returned value is determined by the types of the base and exponent.
|
||||
The following rules are applied to determine the result type:
|
||||
|
||||
* If either of the base or exponent are of a floating point type, the result will be a double
|
||||
* Otherwise, if either the base or the exponent are 64-bit (long or unsigned long), the result will be a long
|
||||
* Otherwise, the result will be a 32-bit integer (this covers all other numeric types, including int, short and byte)
|
||||
|
||||
For example, using simple integers as arguments will lead to an integer result:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=powII]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=powII-result]
|
||||
|===
|
||||
|
||||
NOTE: The actual power function is performed using double precision values for all cases.
|
||||
This means that for very large non-floating point values there is a small chance that the
|
||||
operation can lead to slightly different answers than expected.
|
||||
However, a more likely outcome of very large non-floating point values is numerical overflow.
|
||||
|
||||
==== Arithmetic errors
|
||||
|
||||
Arithmetic errors and numeric overflow do not result in an error. Instead, the result will be `null`
|
||||
and a warning for the `ArithmeticException` added.
|
||||
For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=powULOverrun]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=powULOverrun-warning]
|
||||
|===
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=powULOverrun-result]
|
||||
|===
|
||||
|
||||
If it is desired to protect against numerical overruns, use `to_double` on either of the arguments:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=pow2d]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=pow2d-result]
|
||||
|===
|
||||
|
||||
==== Fractional exponents
|
||||
|
||||
The exponent can be a fraction, which is similar to performing a root.
|
||||
For example, the exponent of `0.5` will give the square root of the base:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=powID-sqrt]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=powID-sqrt-result]
|
||||
|===
|
||||
|
||||
==== Table of supported input and output types
|
||||
|
||||
For clarity, the following table describes the output result type for all combinations of numeric input types:
|
||||
|
||||
include::types/pow.asciidoc[]
|
|
@ -0,0 +1,14 @@
|
|||
[[esql-round]]
|
||||
=== `ROUND`
|
||||
Rounds a number to the closest number with the specified number of digits.
|
||||
Defaults to 0 digits if no number of digits is provided. If the specified number
|
||||
of digits is negative, rounds to the number of digits left of the decimal point.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=round]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=round-result]
|
||||
|===
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-rtrim]]
|
||||
=== `RTRIM`
|
||||
Removes trailing whitespaces from strings.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=rtrim]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=rtrim-result]
|
||||
|===
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-sin]]
|
||||
=== `SIN`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/sin.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Sine_and_cosine[Sine] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=sin]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=sin-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/sin.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-sinh]]
|
||||
=== `SINH`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/sinh.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Hyperbolic_functions[Sine] hyperbolic function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=sinh]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=sinh-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/sinh.asciidoc[]
|
|
@ -0,0 +1,17 @@
|
|||
[[esql-split]]
|
||||
=== `SPLIT`
|
||||
Split a single valued string into multiple strings. For example:
|
||||
|
||||
[source,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=split]
|
||||
----
|
||||
|
||||
Which splits `"foo;bar;baz;qux;quux;corge"` on `;` and returns an array:
|
||||
|
||||
[%header,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=split-result]
|
||||
|===
|
||||
|
||||
WARNING: Only single byte delimiters are currently supported.
|
|
@ -0,0 +1,22 @@
|
|||
[[esql-sqrt]]
|
||||
=== `SQRT`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/sqrt.svg[Embedded,opts=inline]
|
||||
|
||||
Returns the square root of a number. The input can be any numeric value, the return value
|
||||
is always a double.
|
||||
|
||||
Square roots of negative numbers are NaN. Square roots of infinites are infinite.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=sqrt]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=sqrt-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/sqrt.asciidoc[]
|
|
@ -0,0 +1,13 @@
|
|||
[[esql-starts_with]]
|
||||
=== `STARTS_WITH`
|
||||
Returns a boolean that indicates whether a keyword string starts with another
|
||||
string:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=startsWith]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=startsWith-result]
|
||||
|===
|
|
@ -0,0 +1,37 @@
|
|||
[[esql-substring]]
|
||||
=== `SUBSTRING`
|
||||
Returns a substring of a string, specified by a start position and an optional
|
||||
length. This example returns the first three characters of every last name:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=substring]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=substring-result]
|
||||
|===
|
||||
|
||||
A negative start position is interpreted as being relative to the end of the
|
||||
string. This example returns the last three characters of of every last name:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=substringEnd]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=substringEnd-result]
|
||||
|===
|
||||
|
||||
If length is omitted, substring returns the remainder of the string. This
|
||||
example returns all characters except for the first:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/docs.csv-spec[tag=substringRemainder]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/docs.csv-spec[tag=substringRemainder-result]
|
||||
|===
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-tan]]
|
||||
=== `TAN`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/tan.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Sine_and_cosine[Tangent] trigonometric function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=tan]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=tan-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/tan.asciidoc[]
|
|
@ -0,0 +1,19 @@
|
|||
[[esql-tanh]]
|
||||
=== `TANH`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/tanh.svg[Embedded,opts=inline]
|
||||
|
||||
https://en.wikipedia.org/wiki/Hyperbolic_functions[Tangent] hyperbolic function.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=tanh]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=tanh-result]
|
||||
|===
|
||||
|
||||
Supported types:
|
||||
|
||||
include::types/tanh.asciidoc[]
|
|
@ -0,0 +1,15 @@
|
|||
[[esql-tau]]
|
||||
=== `TAU`
|
||||
[.text-center]
|
||||
image::esql/functions/signature/tau.svg[Embedded,opts=inline]
|
||||
|
||||
The https://tauday.com/tau-manifesto[ratio] of a circle's circumference to its radius.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/math.csv-spec[tag=tau]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/math.csv-spec[tag=tau-result]
|
||||
|===
|
|
@ -0,0 +1,24 @@
|
|||
[[esql-to_boolean]]
|
||||
=== `TO_BOOLEAN`
|
||||
Converts an input value to a boolean value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a string or numeric type.
|
||||
|
||||
A string value of *"true"* will be case-insensitive converted to the Boolean
|
||||
*true*. For anything else, including the empty string, the function will
|
||||
return *false*. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/boolean.csv-spec[tag=to_boolean]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/boolean.csv-spec[tag=to_boolean-result]
|
||||
|===
|
||||
|
||||
The numerical value of *0* will be converted to *false*, anything else will be
|
||||
converted to *true*.
|
||||
|
||||
Alias: TO_BOOL
|
|
@ -0,0 +1,46 @@
|
|||
[[esql-to_datetime]]
|
||||
=== `TO_DATETIME`
|
||||
Converts an input value to a date value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a string or numeric type.
|
||||
|
||||
A string will only be successfully converted if it's respecting the format
|
||||
`yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` (to convert dates in other formats, use <<esql-date_parse>>). For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/date.csv-spec[tag=to_datetime-str]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/date.csv-spec[tag=to_datetime-str-result]
|
||||
|===
|
||||
|
||||
Note that in this example, the last value in the source multi-valued
|
||||
field has not been converted. The reason being that if the date format is not
|
||||
respected, the conversion will result in a *null* value. When this happens a
|
||||
_Warning_ header is added to the response. The header will provide information
|
||||
on the source of the failure:
|
||||
|
||||
`"Line 1:112: evaluation of [TO_DATETIME(string)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"java.lang.IllegalArgumentException: failed to parse date field [1964-06-02 00:00:00] with format [yyyy-MM-dd'T'HH:mm:ss.SSS'Z']"`
|
||||
|
||||
|
||||
If the input parameter is of a numeric type, its value will be interpreted as
|
||||
milliseconds since the https://en.wikipedia.org/wiki/Unix_time[Unix epoch].
|
||||
For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/date.csv-spec[tag=to_datetime-int]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/date.csv-spec[tag=to_datetime-int-result]
|
||||
|===
|
||||
|
||||
Alias: TO_DT
|
|
@ -0,0 +1,18 @@
|
|||
[[esql-to_degrees]]
|
||||
=== `TO_DEGREES`
|
||||
Converts a number in https://en.wikipedia.org/wiki/Radian[radians]
|
||||
to https://en.wikipedia.org/wiki/Degree_(angle)[degrees].
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a numeric type and result is always `double`.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_degrees]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_degrees-result]
|
||||
|===
|
|
@ -0,0 +1,37 @@
|
|||
[[esql-to_double]]
|
||||
=== `TO_DOUBLE`
|
||||
Converts an input value to a double value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a boolean, date, string or numeric type.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_double-str]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_double-str-result]
|
||||
|===
|
||||
|
||||
Note that in this example, the last conversion of the string isn't
|
||||
possible. When this happens, the result is a *null* value. In this case a
|
||||
_Warning_ header is added to the response. The header will provide information
|
||||
on the source of the failure:
|
||||
|
||||
`"Line 1:115: evaluation of [TO_DOUBLE(str2)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"java.lang.NumberFormatException: For input string: \"foo\""`
|
||||
|
||||
|
||||
If the input parameter is of a date type, its value will be interpreted as
|
||||
milliseconds since the https://en.wikipedia.org/wiki/Unix_time[Unix epoch],
|
||||
converted to double.
|
||||
|
||||
Boolean *true* will be converted to double *1.0*, *false* to *0.0*.
|
||||
|
||||
Alias: TO_DBL
|
|
@ -0,0 +1,37 @@
|
|||
[[esql-to_integer]]
|
||||
=== `TO_INTEGER`
|
||||
Converts an input value to an integer value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a boolean, date, string or numeric type.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_int-long]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_int-long-result]
|
||||
|===
|
||||
|
||||
Note that in this example, the last value of the multi-valued field cannot
|
||||
be converted as an integer. When this happens, the result is a *null* value.
|
||||
In this case a _Warning_ header is added to the response. The header will
|
||||
provide information on the source of the failure:
|
||||
|
||||
`"Line 1:61: evaluation of [TO_INTEGER(long)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"org.elasticsearch.xpack.ql.QlIllegalArgumentException: [501379200000] out of [integer] range"`
|
||||
|
||||
|
||||
If the input parameter is of a date type, its value will be interpreted as
|
||||
milliseconds since the https://en.wikipedia.org/wiki/Unix_time[Unix epoch],
|
||||
converted to integer.
|
||||
|
||||
Boolean *true* will be converted to integer *1*, *false* to *0*.
|
||||
|
||||
Alias: TO_INT
|
|
@ -0,0 +1,27 @@
|
|||
[[esql-to_ip]]
|
||||
=== `TO_IP`
|
||||
Converts an input string to an IP value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/ip.csv-spec[tag=to_ip]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/ip.csv-spec[tag=to_ip-result]
|
||||
|===
|
||||
|
||||
Note that in the example above the last conversion of the string isn't
|
||||
possible. When this happens, the result is a *null* value. In this case a
|
||||
_Warning_ header is added to the response. The header will provide information
|
||||
on the source of the failure:
|
||||
|
||||
`"Line 1:68: evaluation of [TO_IP(str2)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"java.lang.IllegalArgumentException: 'foo' is not an IP string literal."`
|
|
@ -0,0 +1,35 @@
|
|||
[[esql-to_long]]
|
||||
=== `TO_LONG`
|
||||
Converts an input value to a long value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a boolean, date, string or numeric type.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_long-str]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_long-str-result]
|
||||
|===
|
||||
|
||||
Note that in this example, the last conversion of the string isn't
|
||||
possible. When this happens, the result is a *null* value. In this case a
|
||||
_Warning_ header is added to the response. The header will provide information
|
||||
on the source of the failure:
|
||||
|
||||
`"Line 1:113: evaluation of [TO_LONG(str3)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"java.lang.NumberFormatException: For input string: \"foo\""`
|
||||
|
||||
|
||||
If the input parameter is of a date type, its value will be interpreted as
|
||||
milliseconds since the https://en.wikipedia.org/wiki/Unix_time[Unix epoch],
|
||||
converted to long.
|
||||
|
||||
Boolean *true* will be converted to long *1*, *false* to *0*.
|
|
@ -0,0 +1,18 @@
|
|||
[[esql-to_radians]]
|
||||
=== `TO_RADIANS`
|
||||
Converts a number in https://en.wikipedia.org/wiki/Degree_(angle)[degrees] to
|
||||
https://en.wikipedia.org/wiki/Radian[radians].
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a numeric type and result is always `double`.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_radians]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/floats.csv-spec[tag=to_radians-result]
|
||||
|===
|
|
@ -0,0 +1,25 @@
|
|||
[[esql-to_string]]
|
||||
=== `TO_STRING`
|
||||
Converts a field into a string. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=to_string]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=to_string-result]
|
||||
|===
|
||||
|
||||
It also works fine on multivalued fields:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=to_string_multivalue]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=to_string_multivalue-result]
|
||||
|===
|
||||
|
||||
Alias: TO_STR
|
|
@ -0,0 +1,37 @@
|
|||
[[esql-to_unsigned_long]]
|
||||
=== `TO_UNSIGNED_LONG`
|
||||
Converts an input value to an unsigned long value.
|
||||
|
||||
The input can be a single- or multi-valued field or an expression. The input
|
||||
type must be of a boolean, date, string or numeric type.
|
||||
|
||||
Example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_unsigned_long-str]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/ints.csv-spec[tag=to_unsigned_long-str-result]
|
||||
|===
|
||||
|
||||
Note that in this example, the last conversion of the string isn't
|
||||
possible. When this happens, the result is a *null* value. In this case a
|
||||
_Warning_ header is added to the response. The header will provide information
|
||||
on the source of the failure:
|
||||
|
||||
`"Line 1:133: evaluation of [TO_UL(str3)] failed, treating result as null. Only first 20 failures recorded."`
|
||||
|
||||
A following header will contain the failure reason and the offending value:
|
||||
|
||||
`"java.lang.NumberFormatException: Character f is neither a decimal digit number, decimal point, nor \"e\" notation exponential mark."`
|
||||
|
||||
|
||||
If the input parameter is of a date type, its value will be interpreted as
|
||||
milliseconds since the https://en.wikipedia.org/wiki/Unix_time[Unix epoch],
|
||||
converted to unsigned long.
|
||||
|
||||
Boolean *true* will be converted to unsigned long *1*, *false* to *0*.
|
||||
|
||||
Alias: TO_ULONG, TO_UL
|
|
@ -0,0 +1,16 @@
|
|||
[[esql-to_version]]
|
||||
=== `TO_VERSION`
|
||||
Converts an input string to a version value. For example:
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/version.csv-spec[tag=to_version]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/version.csv-spec[tag=to_version-result]
|
||||
|===
|
||||
|
||||
The input can be a single- or multi-valued field or an expression.
|
||||
|
||||
Alias: TO_VER
|
|
@ -0,0 +1,12 @@
|
|||
[[esql-trim]]
|
||||
=== `TRIM`
|
||||
Removes leading and trailing whitespaces from strings.
|
||||
|
||||
[source.merge.styled,esql]
|
||||
----
|
||||
include::{esql-specs}/string.csv-spec[tag=trim]
|
||||
----
|
||||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
include::{esql-specs}/string.csv-spec[tag=trim-result]
|
||||
|===
|
|
@ -0,0 +1,8 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
n | result
|
||||
double | double
|
||||
integer | integer
|
||||
long | long
|
||||
unsigned_long | unsigned_long
|
||||
|===
|
|
@ -0,0 +1,8 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
n | result
|
||||
double | double
|
||||
integer | double
|
||||
long | double
|
||||
unsigned_long | double
|
||||
|===
|
|
@ -0,0 +1,8 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
n | result
|
||||
double | double
|
||||
integer | double
|
||||
long | double
|
||||
unsigned_long | double
|
||||
|===
|
|
@ -0,0 +1,8 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
n | result
|
||||
double | double
|
||||
integer | double
|
||||
long | double
|
||||
unsigned_long | double
|
||||
|===
|
|
@ -0,0 +1,20 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
y | x | result
|
||||
double | double | double
|
||||
double | integer | double
|
||||
double | long | double
|
||||
double | unsigned_long | double
|
||||
integer | double | double
|
||||
integer | integer | double
|
||||
integer | long | double
|
||||
integer | unsigned_long | double
|
||||
long | double | double
|
||||
long | integer | double
|
||||
long | long | double
|
||||
long | unsigned_long | double
|
||||
unsigned_long | double | double
|
||||
unsigned_long | integer | double
|
||||
unsigned_long | long | double
|
||||
unsigned_long | unsigned_long | double
|
||||
|===
|
|
@ -0,0 +1,5 @@
|
|||
[%header.monospaced.styled,format=dsv,separator=|]
|
||||
|===
|
||||
arg1 | arg2... | result
|
||||
|
||||
|===
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue