[8.x] [ES|QL] Enhances the inline documentation experience (#192156) (#193444)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[ES|QL] Enhances the inline documentation experience
(#192156)](https://github.com/elastic/kibana/pull/192156)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Stratoula
Kalafateli","email":"efstratia.kalafateli@elastic.co"},"sourceCommit":{"committedDate":"2024-09-19T15:10:39Z","message":"[ES|QL]
Enhances the inline documentation experience (#192156)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/166907\r\n\r\nThis
PR:\r\n\r\n1. Changes the inline docs implementation to a flyout for
Discover\r\n\r\n<img width=\"1256\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3665c73a-82d5-49b9-88c3-e129eda63885\">\r\n\r\n2.
Adds the flyout to open from the help menu and removes it from
the\r\neditor footer\r\n\r\n3. For the inline editing changes the docs
to be rendered as a component\r\ninside the editor (exactly as the
history component)\r\n\r\nNote: The documentation in the inline editing
has limited space (same\r\nproblem has the history component). I need to
sync with Ryan to see what\r\nwe can do, I am exploring some ideas in
follow up PRs\r\n\r\n<img width=\"647\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2fa9fcc3-2a07-4bea-b675-5ae6578696d3\">\r\n\r\n4.
Moves the esql docs to the language package and the script
associated\r\nto this\r\n\r\n### Follow up\r\n- The language package
should be renamed as the `popover` makes sense\r\nonly for the formula
implementation now. I will do it after this PR gets\r\nmerged\r\n- See
how we can give more space to the docs / history container when
in\r\ninline mode\r\n\r\n### Note\r\nThe async bundle got increased as
we want the ES|QL docs in unified\r\nsearch too. It wont be a problem as
is loaded asynchronously.\r\n\r\n### Checklist\r\n\r\n- [ ] Any text
added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[ ] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Ryan Keairns <contactryank@gmail.com>\r\nCo-authored-by: Drew Tate
<andrew.tate@elastic.co>\r\nCo-authored-by: Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"dfbd7de3f53cae4b81d8643283f106cbf16e3415","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","v9.0.0","backport:prev-minor","Feature:ES|QL","Team:ESQL","v8.16.0"],"title":"[ES|QL]
Enhances the inline documentation
experience","number":192156,"url":"https://github.com/elastic/kibana/pull/192156","mergeCommit":{"message":"[ES|QL]
Enhances the inline documentation experience (#192156)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/166907\r\n\r\nThis
PR:\r\n\r\n1. Changes the inline docs implementation to a flyout for
Discover\r\n\r\n<img width=\"1256\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3665c73a-82d5-49b9-88c3-e129eda63885\">\r\n\r\n2.
Adds the flyout to open from the help menu and removes it from
the\r\neditor footer\r\n\r\n3. For the inline editing changes the docs
to be rendered as a component\r\ninside the editor (exactly as the
history component)\r\n\r\nNote: The documentation in the inline editing
has limited space (same\r\nproblem has the history component). I need to
sync with Ryan to see what\r\nwe can do, I am exploring some ideas in
follow up PRs\r\n\r\n<img width=\"647\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2fa9fcc3-2a07-4bea-b675-5ae6578696d3\">\r\n\r\n4.
Moves the esql docs to the language package and the script
associated\r\nto this\r\n\r\n### Follow up\r\n- The language package
should be renamed as the `popover` makes sense\r\nonly for the formula
implementation now. I will do it after this PR gets\r\nmerged\r\n- See
how we can give more space to the docs / history container when
in\r\ninline mode\r\n\r\n### Note\r\nThe async bundle got increased as
we want the ES|QL docs in unified\r\nsearch too. It wont be a problem as
is loaded asynchronously.\r\n\r\n### Checklist\r\n\r\n- [ ] Any text
added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[ ] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Ryan Keairns <contactryank@gmail.com>\r\nCo-authored-by: Drew Tate
<andrew.tate@elastic.co>\r\nCo-authored-by: Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"dfbd7de3f53cae4b81d8643283f106cbf16e3415"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/192156","number":192156,"mergeCommit":{"message":"[ES|QL]
Enhances the inline documentation experience (#192156)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/166907\r\n\r\nThis
PR:\r\n\r\n1. Changes the inline docs implementation to a flyout for
Discover\r\n\r\n<img width=\"1256\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/3665c73a-82d5-49b9-88c3-e129eda63885\">\r\n\r\n2.
Adds the flyout to open from the help menu and removes it from
the\r\neditor footer\r\n\r\n3. For the inline editing changes the docs
to be rendered as a component\r\ninside the editor (exactly as the
history component)\r\n\r\nNote: The documentation in the inline editing
has limited space (same\r\nproblem has the history component). I need to
sync with Ryan to see what\r\nwe can do, I am exploring some ideas in
follow up PRs\r\n\r\n<img width=\"647\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/2fa9fcc3-2a07-4bea-b675-5ae6578696d3\">\r\n\r\n4.
Moves the esql docs to the language package and the script
associated\r\nto this\r\n\r\n### Follow up\r\n- The language package
should be renamed as the `popover` makes sense\r\nonly for the formula
implementation now. I will do it after this PR gets\r\nmerged\r\n- See
how we can give more space to the docs / history container when
in\r\ninline mode\r\n\r\n### Note\r\nThe async bundle got increased as
we want the ES|QL docs in unified\r\nsearch too. It wont be a problem as
is loaded asynchronously.\r\n\r\n### Checklist\r\n\r\n- [ ] Any text
added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[ ] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Ryan Keairns <contactryank@gmail.com>\r\nCo-authored-by: Drew Tate
<andrew.tate@elastic.co>\r\nCo-authored-by: Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"dfbd7de3f53cae4b81d8643283f106cbf16e3415"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
This commit is contained in:
Kibana Machine 2024-09-20 02:38:58 +10:00 committed by GitHub
parent b2e6263d94
commit c5ff79a1a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 2199 additions and 1850 deletions

View file

@ -2,7 +2,7 @@
set -euo pipefail
VALIDATION_PACKAGE_DIR="packages/kbn-esql-validation-autocomplete"
EDITOR_PACKAGE_DIR="packages/kbn-text-based-editor"
EDITOR_PACKAGE_DIR="packages/kbn-language-documentation-popover"
GIT_SCOPE="$VALIDATION_PACKAGE_DIR/**/* $EDITOR_PACKAGE_DIR/**/*"
report_main_step () {

View file

@ -6,7 +6,8 @@
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
export { LanguageDocumentationPopover } from './src/components/documentation_popover';
export { LanguageDocumentationPopoverContent } from './src/components/documentation_content';
export type { LanguageDocumentationSections } from './src/components/documentation_content';
export { LanguageDocumentationPopover } from './src/components/as_popover';
export { LanguageDocumentationPopoverContent } from './src/components/as_popover/popover_content';
export { LanguageDocumentationFlyout } from './src/components/as_flyout';
export { LanguageDocumentationInline } from './src/components/as_inline';
export type { LanguageDocumentationSections } from './src/types';

View file

@ -5,5 +5,10 @@
"private": true,
"sideEffects": [
"*.scss"
]
}
],
"scripts": {
"make:docs": "ts-node --transpileOnly scripts/generate_esql_docs.ts",
"postmake:docs": "yarn run lint:fix",
"lint:fix": "cd ../.. && node ./scripts/eslint --fix ./packages/kbn-language-documentation-popover/src/sections/generated"
}
}

View file

@ -11,18 +11,18 @@ import * as recast from 'recast';
const n = recast.types.namedTypes;
import fs from 'fs';
import path from 'path';
import { functions } from '../src/inline_documentation/generated/scalar_functions';
import { functions } from '../src/sections/generated/scalar_functions';
(function () {
const pathToElasticsearch = process.argv[2];
const { scalarFunctions, aggregationFunctions } = loadFunctionDocs(pathToElasticsearch);
writeFunctionDocs(
scalarFunctions,
path.join(__dirname, '../src/inline_documentation/generated/scalar_functions.tsx')
path.join(__dirname, '../src/sections/generated/scalar_functions.tsx')
);
writeFunctionDocs(
aggregationFunctions,
path.join(__dirname, '../src/inline_documentation/generated/aggregation_functions.tsx')
path.join(__dirname, '../src/sections/generated/aggregation_functions.tsx')
);
})();
@ -86,7 +86,7 @@ function writeFunctionDocs(functionDocs: Map<string, string>, pathToDocsFile: st
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.${name}',
'languageDocumentationPopover.documentationESQL.${name}',
{
defaultMessage: '${name.toUpperCase()}',
}
@ -97,7 +97,7 @@ function writeFunctionDocs(functionDocs: Map<string, string>, pathToDocsFile: st
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.${name}.markdown',
'languageDocumentationPopover.documentationESQL.${name}.markdown',
{
defaultMessage: \`${docWithoutLinks.replaceAll('`', '\\`')}\`,
description:

View file

@ -0,0 +1,11 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
// eslint-disable-next-line import/no-extraneous-dependencies
import '@testing-library/jest-dom';

View file

@ -9,7 +9,7 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { LanguageDocumentationPopover } from '../components/documentation_popover';
import { LanguageDocumentationPopover } from '../components/as_popover';
const sections = {
groups: [

View file

@ -0,0 +1,95 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { screen, render, fireEvent, waitFor } from '@testing-library/react';
import { LanguageDocumentationFlyout } from '.';
jest.mock('../../sections', () => {
const module = jest.requireActual('../../sections');
return {
...module,
getESQLDocsSections: () => ({
groups: [
{
label: 'Section one',
description: 'Section 1 description',
items: [],
},
{
label: 'Section two',
items: [
{
label: 'Section two item 1',
description: 'Section two item 1 description',
},
{
label: 'Section two item 2',
description: 'Section two item 2 description',
},
],
},
{
label: 'Section three',
items: [
{
label: 'Section three item 1',
description: 'Section three item 1 description',
},
{
label: 'Section three item 2',
description: 'Section three item 2 description',
},
],
},
],
initialSection: <span>Here is the initial section</span>,
}),
};
});
describe('###Documentation flyout component', () => {
const renderFlyout = (linkToDocumentation?: string) => {
return render(
<LanguageDocumentationFlyout
isHelpMenuOpen={true}
onHelpMenuVisibilityChange={jest.fn()}
linkToDocumentation={linkToDocumentation}
/>
);
};
it('has a header element for navigation through the sections', () => {
renderFlyout();
expect(screen.getByTestId('language-documentation-navigation-search')).toBeInTheDocument();
expect(screen.getByTestId('language-documentation-navigation-dropdown')).toBeInTheDocument();
expect(screen.queryByTestId('language-documentation-navigation-link')).not.toBeInTheDocument();
});
it('has a link if linkToDocumentation prop is given', () => {
renderFlyout('meow');
expect(screen.getByTestId('language-documentation-navigation-link')).toBeInTheDocument();
});
it('contains the two last sections', async () => {
renderFlyout();
await waitFor(() => {
expect(screen.getByText('Section two')).toBeInTheDocument();
expect(screen.getByText('Section three')).toBeInTheDocument();
});
});
it('contains the correct section if user updates the search input', async () => {
renderFlyout();
const input = screen.getByTestId('language-documentation-navigation-search');
fireEvent.change(input, { target: { value: 'two' } });
await waitFor(() => {
expect(screen.getByText('Section two')).toBeInTheDocument();
});
});
});

View file

@ -0,0 +1,117 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useCallback, useEffect, useState, useRef, useMemo } from 'react';
import {
EuiFlyout,
useEuiTheme,
EuiFlyoutBody,
EuiFlyoutHeader,
EuiTitle,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { getFilteredGroups } from '../../utils/get_filtered_groups';
import { DocumentationMainContent, DocumentationNavigation } from '../shared';
import { getESQLDocsSections } from '../../sections';
import type { LanguageDocumentationSections } from '../../types';
interface DocumentationFlyoutProps {
isHelpMenuOpen: boolean;
onHelpMenuVisibilityChange: (status: boolean) => void;
searchInDescription?: boolean;
linkToDocumentation?: string;
}
function DocumentationFlyout({
searchInDescription,
linkToDocumentation,
isHelpMenuOpen,
onHelpMenuVisibilityChange,
}: DocumentationFlyoutProps) {
const [documentationSections, setDocumentationSections] =
useState<LanguageDocumentationSections>();
const { euiTheme } = useEuiTheme();
const DEFAULT_WIDTH = euiTheme.base * 34;
const [selectedSection, setSelectedSection] = useState<string | undefined>();
const [searchText, setSearchText] = useState('');
const scrollTargets = useRef<Record<string, HTMLElement>>({});
const onNavigationChange = useCallback((selectedOptions) => {
setSelectedSection(selectedOptions.length ? selectedOptions[0].label : undefined);
if (selectedOptions.length) {
const scrollToElement = scrollTargets.current[selectedOptions[0].label];
scrollToElement.scrollIntoView();
}
}, []);
useEffect(() => {
onHelpMenuVisibilityChange(isHelpMenuOpen ?? false);
}, [isHelpMenuOpen, onHelpMenuVisibilityChange]);
useEffect(() => {
async function getDocumentation() {
const sections = await getESQLDocsSections();
setDocumentationSections(sections);
}
if (!documentationSections) {
getDocumentation();
}
}, [documentationSections]);
const filteredGroups = useMemo(() => {
return getFilteredGroups(searchText, searchInDescription, documentationSections, 1);
}, [documentationSections, searchText, searchInDescription]);
return (
<>
{isHelpMenuOpen && (
<EuiFlyout
ownFocus
onClose={() => onHelpMenuVisibilityChange(false)}
aria-labelledby="esqlInlineDocumentationFlyout"
type="push"
size={DEFAULT_WIDTH}
paddingSize="m"
>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="s">
<h3>
{i18n.translate('languageDocumentationPopover.documentationFlyoutTitle', {
defaultMessage: 'ES|QL quick reference',
})}
</h3>
</EuiTitle>
<EuiSpacer size="m" />
<DocumentationNavigation
searchText={searchText}
setSearchText={setSearchText}
onNavigationChange={onNavigationChange}
filteredGroups={filteredGroups}
linkToDocumentation={linkToDocumentation}
selectedSection={selectedSection}
/>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<DocumentationMainContent
searchText={searchText}
scrollTargets={scrollTargets}
filteredGroups={filteredGroups}
sections={documentationSections}
/>
</EuiFlyoutBody>
</EuiFlyout>
)}
</>
);
}
export const LanguageDocumentationFlyout = React.memo(DocumentationFlyout);

View file

@ -0,0 +1,97 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { screen, render, fireEvent, waitFor } from '@testing-library/react';
import { Markdown } from '@kbn/shared-ux-markdown';
import { LanguageDocumentationInline } from '.';
const mockMarkDownDescription = () => (
<Markdown markdownContent="Section three item 1 blah blah blah" />
);
jest.mock('../../sections', () => {
const module = jest.requireActual('../../sections');
return {
...module,
getESQLDocsSections: () => ({
groups: [
{
label: 'Section one',
description: 'Section 1 description',
items: [],
},
{
label: 'Section two',
items: [
{
label: 'Section two item 1',
description: 'Section two item 1 description',
},
{
label: 'Section two item 2',
description: 'Section two item 2 description',
},
],
},
{
label: 'Section three',
items: [
{
label: 'Section three item 1',
description: mockMarkDownDescription(),
},
{
label: 'Section three item 2',
description: 'Section three item 2 description',
},
],
},
],
initialSection: <span>Here is the initial section</span>,
}),
};
});
describe('###Documentation flyout component', () => {
const renderInlineComponent = (searchInDescription = false) => {
return render(<LanguageDocumentationInline searchInDescription={searchInDescription} />);
};
it('has a header element for navigation through the sections', () => {
renderInlineComponent();
expect(screen.getByTestId('language-documentation-navigation-search')).toBeInTheDocument();
expect(screen.getByTestId('language-documentation-navigation-dropdown')).toBeInTheDocument();
});
it('contains the two last sections', async () => {
renderInlineComponent();
await waitFor(() => {
expect(screen.getByText('Section two')).toBeInTheDocument();
expect(screen.getByText('Section three')).toBeInTheDocument();
});
});
it('contains the correct section if user updates the search input', async () => {
renderInlineComponent();
const input = screen.getByTestId('language-documentation-navigation-search');
fireEvent.change(input, { target: { value: 'two' } });
await waitFor(() => {
expect(screen.getByText('Section two')).toBeInTheDocument();
});
});
it('contains the correct section if user updates the search input with a text that exist in the description', async () => {
renderInlineComponent(true);
const input = screen.getByTestId('language-documentation-navigation-search');
fireEvent.change(input, { target: { value: 'blah' } });
await waitFor(() => {
expect(screen.getByText('Section three')).toBeInTheDocument();
});
});
});

View file

@ -0,0 +1,82 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useCallback, useState, useRef, useMemo, useEffect } from 'react';
import { css } from '@emotion/react';
import { useEuiTheme, euiScrollBarStyles, EuiSpacer } from '@elastic/eui';
import { getFilteredGroups } from '../../utils/get_filtered_groups';
import { DocumentationMainContent, DocumentationNavigation } from '../shared';
import type { LanguageDocumentationSections } from '../../types';
import { getESQLDocsSections } from '../../sections';
interface DocumentationInlineProps {
searchInDescription?: boolean;
}
const MAX_HEIGHT = 250;
function DocumentationInline({ searchInDescription }: DocumentationInlineProps) {
const theme = useEuiTheme();
const [documentationSections, setDocumentationSections] =
useState<LanguageDocumentationSections>();
const scrollBarStyles = euiScrollBarStyles(theme);
const [selectedSection, setSelectedSection] = useState<string | undefined>();
const [searchText, setSearchText] = useState('');
const scrollTargets = useRef<Record<string, HTMLElement>>({});
useEffect(() => {
async function getDocumentation() {
const sections = await getESQLDocsSections();
setDocumentationSections(sections);
}
if (!documentationSections) {
getDocumentation();
}
}, [documentationSections]);
const filteredGroups = useMemo(() => {
return getFilteredGroups(searchText, searchInDescription, documentationSections, 1);
}, [documentationSections, searchText, searchInDescription]);
const onNavigationChange = useCallback((selectedOptions) => {
setSelectedSection(selectedOptions.length ? selectedOptions[0].label : undefined);
if (selectedOptions.length) {
const scrollToElement = scrollTargets.current[selectedOptions[0].label];
scrollToElement.scrollIntoView();
}
}, []);
return (
<div
css={css`
padding: ${theme.euiTheme.size.base};
max-height: ${MAX_HEIGHT}px;
overflow-y: auto;
${scrollBarStyles}
`}
>
<DocumentationNavigation
searchText={searchText}
setSearchText={setSearchText}
onNavigationChange={onNavigationChange}
filteredGroups={filteredGroups}
selectedSection={selectedSection}
/>
<EuiSpacer size="s" />
<DocumentationMainContent
searchText={searchText}
scrollTargets={scrollTargets}
filteredGroups={filteredGroups}
sections={documentationSections}
/>
</div>
);
}
export const LanguageDocumentationInline = React.memo(DocumentationInline);

View file

@ -16,10 +16,8 @@ import {
EuiButtonIconProps,
EuiOutsideClickDetector,
} from '@elastic/eui';
import {
type LanguageDocumentationSections,
LanguageDocumentationPopoverContent,
} from './documentation_content';
import { LanguageDocumentationPopoverContent } from './popover_content';
import type { LanguageDocumentationSections } from '../../types';
interface DocumentationPopoverProps {
language: string;

View file

@ -11,7 +11,7 @@ import React from 'react';
import { mountWithIntl, findTestSubject } from '@kbn/test-jest-helpers';
import { act } from 'react-dom/test-utils';
import { Markdown } from '@kbn/shared-ux-markdown';
import { LanguageDocumentationPopoverContent } from './documentation_content';
import { LanguageDocumentationPopoverContent } from './popover_content';
describe('###Documentation popover content', () => {
const sections = {

View file

@ -6,8 +6,7 @@
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef, useState, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiFlexGroup,
@ -22,19 +21,11 @@ import {
EuiSpacer,
EuiLink,
} from '@elastic/eui';
import { elementToString } from '../utils/element_to_string';
import { getFilteredGroups } from '../../utils/get_filtered_groups';
import type { LanguageDocumentationSections } from '../../types';
import './documentation.scss';
export interface LanguageDocumentationSections {
groups: Array<{
label: string;
description?: string;
items: Array<{ label: string; description?: JSX.Element }>;
}>;
initialSection: JSX.Element;
}
interface DocumentationProps {
language: string;
sections?: LanguageDocumentationSections;
@ -61,29 +52,9 @@ function DocumentationContent({
const [searchText, setSearchText] = useState('');
const normalizedSearchText = searchText.trim().toLocaleLowerCase();
const filteredGroups = sections?.groups
.map((group) => {
const items = group.items.filter((helpItem) => {
return (
!normalizedSearchText ||
helpItem.label.toLocaleLowerCase().includes(normalizedSearchText) ||
// Converting the JSX element to a string first
(searchInDescription &&
elementToString(helpItem.description)
?.toLocaleLowerCase()
.includes(normalizedSearchText))
);
});
return { ...group, items };
})
.filter((group) => {
if (group.items.length > 0 || !normalizedSearchText) {
return true;
}
return group.label.toLocaleLowerCase().includes(normalizedSearchText);
});
const filteredGroups = useMemo(() => {
return getFilteredGroups(searchText, searchInDescription, sections);
}, [sections, searchText, searchInDescription]);
return (
<>
@ -158,12 +129,12 @@ function DocumentationContent({
</h6>
</EuiTitle>
{helpGroup.items.length ? (
{helpGroup.options.length ? (
<>
<EuiSpacer size="s" />
<EuiListGroup gutterSize="none">
{helpGroup.items.map((helpItem) => {
{helpGroup.options.map((helpItem) => {
return (
<EuiListGroupItem
key={helpItem.label}

View file

@ -0,0 +1,82 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { EuiFlexGroup, EuiText } from '@elastic/eui';
import type { LanguageDocumentationSections } from '../../types';
interface DocumentationContentProps {
searchText: string;
scrollTargets: React.MutableRefObject<{ [key: string]: HTMLElement }>;
filteredGroups?: Array<{
label: string;
description?: string;
options: Array<{ label: string; description?: JSX.Element | undefined }>;
}>;
sections?: LanguageDocumentationSections;
}
function DocumentationContent({
searchText,
scrollTargets,
filteredGroups,
sections,
}: DocumentationContentProps) {
return (
<>
<EuiFlexGroup gutterSize="none" responsive={false} direction="column">
<EuiText size="s">
{!searchText && (
<section
ref={(el) => {
if (el && sections?.groups?.length) {
scrollTargets.current[sections.groups[0].label] = el;
}
}}
>
{sections?.initialSection}
</section>
)}
{filteredGroups?.map((helpGroup, index) => {
return (
<section
key={helpGroup.label}
ref={(el) => {
if (el) {
scrollTargets.current[helpGroup.label] = el;
}
}}
>
<h2>{helpGroup.label}</h2>
<p>{helpGroup.description}</p>
{filteredGroups?.[index].options.map((helpItem) => {
return (
<article
key={helpItem.label}
ref={(el) => {
if (el) {
scrollTargets.current[helpItem.label] = el;
}
}}
>
{helpItem.description}
</article>
);
})}
</section>
);
})}
</EuiText>
</EuiFlexGroup>
</>
);
}
export const DocumentationMainContent = React.memo(DocumentationContent);

View file

@ -0,0 +1,109 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { css } from '@emotion/react';
import {
EuiFlexItem,
EuiFlexGroup,
EuiFormRow,
EuiLink,
EuiText,
useEuiTheme,
EuiFieldSearch,
EuiComboBox,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
interface DocumentationNavProps {
searchText: string;
setSearchText: (text: string) => void;
onNavigationChange: (selectedOptions: Array<{ label: string }>) => void;
filteredGroups?: Array<{ label: string }>;
linkToDocumentation?: string;
selectedSection?: string;
}
function DocumentationNav({
searchText,
setSearchText,
onNavigationChange,
filteredGroups,
linkToDocumentation,
selectedSection,
}: DocumentationNavProps) {
const { euiTheme } = useEuiTheme();
return (
<>
<EuiFlexGroup gutterSize="none" responsive={false} direction="column">
<EuiFlexItem grow={true}>
<EuiFormRow
fullWidth
label={i18n.translate('languageDocumentationPopover.esqlDocsLabel', {
defaultMessage: 'Select or search topics',
})}
labelAppend={
linkToDocumentation && (
<EuiText size="xs">
<EuiLink
external
href={linkToDocumentation}
target="_blank"
data-test-subj="language-documentation-navigation-link"
>
{i18n.translate('languageDocumentationPopover.esqlDocsLinkLabel', {
defaultMessage: 'View full ES|QL documentation',
})}
</EuiLink>
</EuiText>
)
}
>
<EuiComboBox
aria-label={i18n.translate('languageDocumentationPopover.navigationAriaLabel', {
defaultMessage: 'Navigate through the documentation',
})}
placeholder={i18n.translate('languageDocumentationPopover.navigationPlaceholder', {
defaultMessage: 'Commands and functions',
})}
data-test-subj="language-documentation-navigation-dropdown"
options={filteredGroups}
selectedOptions={selectedSection ? [{ label: selectedSection }] : []}
singleSelection={{ asPlainText: true }}
onChange={onNavigationChange}
compressed
fullWidth
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem
grow={false}
css={css`
padding: ${euiTheme.size.s} 0;
`}
>
<EuiFieldSearch
value={searchText}
onChange={(e) => {
setSearchText(e.target.value);
}}
data-test-subj="language-documentation-navigation-search"
placeholder={i18n.translate('languageDocumentationPopover.searchPlaceholder', {
defaultMessage: 'Search',
})}
fullWidth
compressed
/>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
}
export const DocumentationNavigation = React.memo(DocumentationNav);

View file

@ -0,0 +1,11 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
export { DocumentationNavigation } from './documentation_navigation';
export { DocumentationMainContent } from './documentation_content';

View file

@ -17,11 +17,8 @@ const Markdown = (props: Parameters<typeof SharedUXMarkdown>[0]) => (
export const initialSection = (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.markdown',
{
defaultMessage: `## ES|QL
markdownContent={i18n.translate('languageDocumentationPopover.documentationESQL.markdown', {
defaultMessage: `
An ES|QL (Elasticsearch query language) query consists of a series of commands, separated by pipe characters: \`|\`. Each query starts with a **source command**, which produces a table, typically with data from Elasticsearch.
A source command can be followed by one or more **processing commands**. Processing commands can change the output table of the previous command by adding, removing, and changing rows and columns.
@ -34,34 +31,30 @@ source-command
The result of a query is the table produced by the final processing command.
`,
}
)}
})}
/>
);
export const sourceCommands = {
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.sourceCommands', {
label: i18n.translate('languageDocumentationPopover.documentationESQL.sourceCommands', {
defaultMessage: 'Source commands',
}),
description: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.commandsDescription',
'languageDocumentationPopover.documentationESQL.commandsDescription',
{
defaultMessage: `A source command produces a table, typically with data from Elasticsearch. ES|QL supports the following source commands.`,
}
),
items: [
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from',
{
defaultMessage: 'FROM',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.from', {
defaultMessage: 'FROM',
}),
description: (
<Markdown
openLinksInNewTab={true}
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from.markdown',
'languageDocumentationPopover.documentationESQL.from.markdown',
{
defaultMessage: `### FROM
The \`FROM\` source command returns a table with up to 10,000 documents from a data stream, index, or alias. Each row in the resulting table represents a document. Each column corresponds to a field, and can be accessed by the name of that field.
@ -119,16 +112,13 @@ FROM employees [METADATA _index, _id]
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.row',
{
defaultMessage: 'ROW',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.row', {
defaultMessage: 'ROW',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.row.markdown',
'languageDocumentationPopover.documentationESQL.row.markdown',
{
defaultMessage: `### ROW
The \`ROW\` source command produces a row with one or more columns with values that you specify. This can be useful for testing.
@ -157,16 +147,13 @@ ROW a = ROUND(1.23, 0)
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.show',
{
defaultMessage: 'SHOW',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.show', {
defaultMessage: 'SHOW',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.show.markdown',
'languageDocumentationPopover.documentationESQL.show.markdown',
{
defaultMessage: `### SHOW
The \`SHOW <item>\` source command returns information about the deployment and its capabilities:
@ -186,28 +173,25 @@ The \`SHOW <item>\` source command returns information about the deployment and
};
export const processingCommands = {
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.processingCommands', {
label: i18n.translate('languageDocumentationPopover.documentationESQL.processingCommands', {
defaultMessage: 'Processing commands',
}),
description: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.processingCommandsDescription',
'languageDocumentationPopover.documentationESQL.processingCommandsDescription',
{
defaultMessage: `Processing commands change an input table by adding, removing, or changing rows and columns. ES|QL supports the following processing commands.`,
}
),
items: [
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dissect',
{
defaultMessage: 'DISSECT',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.dissect', {
defaultMessage: 'DISSECT',
}),
description: (
<Markdown
openLinksInNewTab={true}
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dissect.markdown',
'languageDocumentationPopover.documentationESQL.dissect.markdown',
{
defaultMessage: `### DISSECT
\`DISSECT\` enables you to extract structured data out of a string. \`DISSECT\` matches the string against a delimiter-based pattern, and extracts the specified keys as columns.
@ -227,16 +211,13 @@ ROW a = "1953-01-23T12:15:00Z - some text - 127.0.0.1"
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.drop',
{
defaultMessage: 'DROP',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.drop', {
defaultMessage: 'DROP',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.drop.markdown',
'languageDocumentationPopover.documentationESQL.drop.markdown',
{
defaultMessage: `### DROP
Use \`DROP\` to remove columns from a table:
@ -261,17 +242,14 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.enrich',
{
defaultMessage: 'ENRICH',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.enrich', {
defaultMessage: 'ENRICH',
}),
description: (
<Markdown
openLinksInNewTab={true}
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.enrich.markdown',
'languageDocumentationPopover.documentationESQL.enrich.markdown',
{
defaultMessage: `### ENRICH
You can use \`ENRICH\` to add data from your existing indices to incoming records. Its similar to [ingest enrich](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html), but it works at query time.
@ -317,16 +295,13 @@ In case of name collisions, the newly created fields will override the existing
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eval',
{
defaultMessage: 'EVAL',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.eval', {
defaultMessage: 'EVAL',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eval.markdown',
'languageDocumentationPopover.documentationESQL.eval.markdown',
{
defaultMessage: `### EVAL
\`EVAL\` enables you to add new columns:
@ -356,17 +331,14 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.grok',
{
defaultMessage: 'GROK',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.grok', {
defaultMessage: 'GROK',
}),
description: (
<Markdown
openLinksInNewTab={true}
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.grok.markdown',
'languageDocumentationPopover.documentationESQL.grok.markdown',
{
defaultMessage: `### GROK
\`GROK\` enables you to extract structured data out of a string. \`GROK\` matches the string against patterns, based on regular expressions, and extracts the specified patterns as columns.
@ -386,16 +358,13 @@ ROW a = "12 15.5 15.6 true"
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.keep',
{
defaultMessage: 'KEEP',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.keep', {
defaultMessage: 'KEEP',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.keep.markdown',
'languageDocumentationPopover.documentationESQL.keep.markdown',
{
defaultMessage: `### KEEP
The \`KEEP\` command enables you to specify what columns are returned and the order in which they are returned.
@ -429,16 +398,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.limit',
{
defaultMessage: 'LIMIT',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.limit', {
defaultMessage: 'LIMIT',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.limit.markdown',
'languageDocumentationPopover.documentationESQL.limit.markdown',
{
defaultMessage: `### LIMIT
The \`LIMIT\` processing command enables you to limit the number of rows:
@ -456,16 +422,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvExpand',
{
defaultMessage: 'MV_EXPAND',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.mvExpand', {
defaultMessage: 'MV_EXPAND',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvExpand.markdown',
'languageDocumentationPopover.documentationESQL.mvExpand.markdown',
{
defaultMessage: `### MV_EXPAND
The \`MV_EXPAND\` processing command expands multivalued fields into one row per value, duplicating other fields:
@ -482,16 +445,13 @@ ROW a=[1,2,3], b="b", j=["a","b"]
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rename',
{
defaultMessage: 'RENAME',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.rename', {
defaultMessage: 'RENAME',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rename.markdown',
'languageDocumentationPopover.documentationESQL.rename.markdown',
{
defaultMessage: `### RENAME
Use \`RENAME\` to rename a column using the following syntax:
@ -527,16 +487,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sort',
{
defaultMessage: 'SORT',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.sort', {
defaultMessage: 'SORT',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sort.markdown',
'languageDocumentationPopover.documentationESQL.sort.markdown',
{
defaultMessage: `### SORT
Use the \`SORT\` command to sort rows on one or more fields:
@ -580,16 +537,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.statsby',
{
defaultMessage: 'STATS ... BY',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.statsby', {
defaultMessage: 'STATS ... BY',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.statsby.markdown',
'languageDocumentationPopover.documentationESQL.statsby.markdown',
{
defaultMessage: `### STATS ... BY
Use \`STATS ... BY\` to group rows according to a common value and calculate one or more aggregated values over the grouped rows.
@ -670,16 +624,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.where',
{
defaultMessage: 'WHERE',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.where', {
defaultMessage: 'WHERE',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.where.markdown',
'languageDocumentationPopover.documentationESQL.where.markdown',
{
defaultMessage: `### WHERE
Use \`WHERE\` to produce a table that contains all the rows from the input table for which the provided condition evaluates to \`true\`:
@ -708,27 +659,24 @@ Refer to **Operators** for an overview of the supported operators.
};
export const groupingFunctions = {
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.groupingFunctions', {
label: i18n.translate('languageDocumentationPopover.documentationESQL.groupingFunctions', {
defaultMessage: 'Grouping functions',
}),
description: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.groupingFunctionsDocumentationESQLDescription',
'languageDocumentationPopover.documentationESQL.groupingFunctionsDocumentationESQLDescription',
{
defaultMessage: `These grouping functions can be used with \`STATS...BY\`:`,
}
),
items: [
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.autoBucketFunction',
{
defaultMessage: 'BUCKET',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.autoBucketFunction', {
defaultMessage: 'BUCKET',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.autoBucketFunction.markdown',
'languageDocumentationPopover.documentationESQL.autoBucketFunction.markdown',
{
defaultMessage: `### BUCKET
Creates groups of values - buckets - out of a datetime or numeric input. The size of the buckets can either be provided directly, or chosen based on a recommended count and values range.
@ -844,27 +792,24 @@ FROM employees
};
export const operators = {
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.operators', {
label: i18n.translate('languageDocumentationPopover.documentationESQL.operators', {
defaultMessage: 'Operators',
}),
description: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.operatorsDocumentationESQLDescription',
'languageDocumentationPopover.documentationESQL.operatorsDocumentationESQLDescription',
{
defaultMessage: `ES|QL supports the following operators:`,
}
),
items: [
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.binaryOperators',
{
defaultMessage: 'Binary operators',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.binaryOperators', {
defaultMessage: 'Binary operators',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.binaryOperators.markdown',
'languageDocumentationPopover.documentationESQL.binaryOperators.markdown',
{
defaultMessage: `### Binary operators
These binary comparison operators are supported:
@ -889,16 +834,13 @@ These binary comparison operators are supported:
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.booleanOperators',
{
defaultMessage: 'Boolean operators',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.booleanOperators', {
defaultMessage: 'Boolean operators',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.booleanOperators.markdown',
'languageDocumentationPopover.documentationESQL.booleanOperators.markdown',
{
defaultMessage: `### Boolean operators
The following boolean operators are supported:
@ -915,19 +857,16 @@ The following boolean operators are supported:
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.castOperator',
{
defaultMessage: 'Cast (::)',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.castOperator', {
defaultMessage: 'Cast (::)',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.castOperator.markdown',
'languageDocumentationPopover.documentationESQL.castOperator.markdown',
{
defaultMessage: `### CAST (\`::\`)
The \`::\` operator provides a convenient alternative syntax to the \`TO_<type>\` type conversion functions.
The \`::\` operator provides a convenient alternative syntax to the \`TO_<type>\` type conversion functions.
Example:
\`\`\`
@ -943,16 +882,13 @@ ROW ver = CONCAT(("0"::INT + 1)::STRING, ".2.3")::VERSION
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.inOperator',
{
defaultMessage: 'IN',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.inOperator', {
defaultMessage: 'IN',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.inOperator.markdown',
'languageDocumentationPopover.documentationESQL.inOperator.markdown',
{
defaultMessage: `### IN
The \`IN\` operator allows testing whether a field or expression equals an element in a list of literals, fields or expressions:
@ -970,16 +906,13 @@ ROW a = 1, b = 4, c = 3
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.stringOperators',
{
defaultMessage: 'LIKE and RLIKE',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.stringOperators', {
defaultMessage: 'LIKE and RLIKE',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.stringOperators.markdown',
'languageDocumentationPopover.documentationESQL.stringOperators.markdown',
{
defaultMessage: `### LIKE and RLIKE
For string comparison using wildcards or regular expressions, use \`LIKE\` or \`RLIKE\`:
@ -1011,16 +944,13 @@ FROM employees
),
},
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.predicates',
{
defaultMessage: 'NULL values',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.predicates', {
defaultMessage: 'NULL values',
}),
description: (
<Markdown
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.predicates.markdown',
'languageDocumentationPopover.documentationESQL.predicates.markdown',
{
defaultMessage: `### NULL values
For NULL comparison use the \`IS NULL\` and \`IS NOT NULL\` predicates:

View file

@ -13,11 +13,11 @@ import { Markdown } from '@kbn/shared-ux-markdown';
// DO NOT RENAME!
export const functions = {
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctions', {
label: i18n.translate('languageDocumentationPopover.documentationESQL.aggregationFunctions', {
defaultMessage: 'Aggregation functions',
}),
description: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctionsDocumentationESQLDescription',
'languageDocumentationPopover.documentationESQL.aggregationFunctionsDocumentationESQLDescription',
{
defaultMessage: `These functions can by used with STATS...BY:`,
}
@ -26,19 +26,16 @@ export const functions = {
items: [
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.avg',
{
defaultMessage: 'AVG',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.avg', {
defaultMessage: 'AVG',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.avg.markdown',
'languageDocumentationPopover.documentationESQL.avg.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -62,19 +59,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.count',
{
defaultMessage: 'COUNT',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.count', {
defaultMessage: 'COUNT',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.count.markdown',
'languageDocumentationPopover.documentationESQL.count.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -98,19 +92,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.count_distinct',
{
defaultMessage: 'COUNT_DISTINCT',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.count_distinct', {
defaultMessage: 'COUNT_DISTINCT',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.count_distinct.markdown',
'languageDocumentationPopover.documentationESQL.count_distinct.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -134,19 +125,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.max',
{
defaultMessage: 'MAX',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.max', {
defaultMessage: 'MAX',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.max.markdown',
'languageDocumentationPopover.documentationESQL.max.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -170,19 +158,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.median',
{
defaultMessage: 'MEDIAN',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.median', {
defaultMessage: 'MEDIAN',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.median.markdown',
'languageDocumentationPopover.documentationESQL.median.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -208,7 +193,7 @@ export const functions = {
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.median_absolute_deviation',
'languageDocumentationPopover.documentationESQL.median_absolute_deviation',
{
defaultMessage: 'MEDIAN_ABSOLUTE_DEVIATION',
}
@ -219,7 +204,7 @@ export const functions = {
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.median_absolute_deviation.markdown',
'languageDocumentationPopover.documentationESQL.median_absolute_deviation.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -246,19 +231,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.min',
{
defaultMessage: 'MIN',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.min', {
defaultMessage: 'MIN',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.min.markdown',
'languageDocumentationPopover.documentationESQL.min.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -282,19 +264,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.percentile',
{
defaultMessage: 'PERCENTILE',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.percentile', {
defaultMessage: 'PERCENTILE',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.percentile.markdown',
'languageDocumentationPopover.documentationESQL.percentile.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -320,19 +299,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_centroid_agg',
{
defaultMessage: 'ST_CENTROID_AGG',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.st_centroid_agg', {
defaultMessage: 'ST_CENTROID_AGG',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_centroid_agg.markdown',
'languageDocumentationPopover.documentationESQL.st_centroid_agg.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -356,19 +332,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sum',
{
defaultMessage: 'SUM',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.sum', {
defaultMessage: 'SUM',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sum.markdown',
'languageDocumentationPopover.documentationESQL.sum.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -392,19 +365,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.top',
{
defaultMessage: 'TOP',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.top', {
defaultMessage: 'TOP',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.top.markdown',
'languageDocumentationPopover.documentationESQL.top.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -428,19 +398,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.values',
{
defaultMessage: 'VALUES',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.values', {
defaultMessage: 'VALUES',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.values.markdown',
'languageDocumentationPopover.documentationESQL.values.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
@ -466,19 +433,16 @@ export const functions = {
},
// Do not edit manually... automatically generated by scripts/generate_esql_docs.ts
{
label: i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.weighted_avg',
{
defaultMessage: 'WEIGHTED_AVG',
}
),
label: i18n.translate('languageDocumentationPopover.documentationESQL.weighted_avg', {
defaultMessage: 'WEIGHTED_AVG',
}),
description: (
<Markdown
openLinksInNewTab
readOnly
enableSoftLineBreaks
markdownContent={i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.weighted_avg.markdown',
'languageDocumentationPopover.documentationESQL.weighted_avg.markdown',
{
defaultMessage: `<!--
This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.

View file

@ -0,0 +1,44 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { i18n } from '@kbn/i18n';
export const getESQLDocsSections = async () => {
const groups: Array<{
label: string;
description?: string;
items: Array<{ label: string; description?: JSX.Element }>;
}> = [];
const {
sourceCommands,
processingCommands,
initialSection,
scalarFunctions,
aggregationFunctions,
groupingFunctions,
operators,
} = await import('./esql_documentation_sections');
groups.push({
label: i18n.translate('languageDocumentationPopover.esqlSections.initialSectionLabel', {
defaultMessage: 'ES|QL',
}),
items: [],
});
groups.push(
sourceCommands,
processingCommands,
scalarFunctions,
aggregationFunctions,
groupingFunctions,
operators
);
return {
groups,
initialSection,
};
};

View file

@ -0,0 +1,17 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
export interface LanguageDocumentationSections {
groups: Array<{
label: string;
description?: string;
items: Array<{ label: string; description?: JSX.Element }>;
}>;
initialSection: JSX.Element;
}

View file

@ -0,0 +1,85 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import { Markdown } from '@kbn/shared-ux-markdown';
import { getFilteredGroups } from './get_filtered_groups';
describe('getFilteredGroups', () => {
const sections = {
groups: [
{
label: 'Section one',
description: 'Section 1 description',
items: [],
},
{
label: 'Section two',
items: [
{
label: 'Section two item 1 blah blah',
description: (
<Markdown readOnly markdownContent={`## Section two item 1 description `} />
),
},
{
label: 'Section two item 2',
description: (
<Markdown readOnly markdownContent={`## Section two item 2 description `} />
),
},
],
},
{
label: 'Section three ',
items: [
{
label: 'Section three item 1',
description: (
<Markdown readOnly markdownContent={`## Section three item 1 description `} />
),
},
{
label: 'Section three item 2',
description: (
<Markdown readOnly markdownContent={`## Section three item 2 description `} />
),
},
],
},
],
initialSection: <span>Here is the initial section</span>,
};
test('Should return the sections as it gets them if the search string is empty', () => {
const filteredSections = getFilteredGroups('', false, sections);
expect(filteredSections).toStrictEqual([
...sections.groups.map((group) => ({ ...group, options: group.items })),
]);
});
test('Should return the 2 last sections as it gets them if the search string is empty and the numOfGroupsToOmit is set to 1', () => {
const filteredSections = getFilteredGroups('', false, sections, 1);
expect(filteredSections).toStrictEqual([
...sections.groups.slice(1).map((group) => ({ ...group, options: group.items })),
]);
});
test('Should return the section two as it gets it if the search string is asking for this', () => {
const filteredSections = getFilteredGroups('tWo', false, sections);
expect(filteredSections).toStrictEqual([
{ ...sections.groups[1], options: sections.groups[1].items },
]);
});
test('Should return the section two filtered on the search string if it is allowed to search in description', () => {
const filteredSections = getFilteredGroups('Section two item 1 blah blah', true, sections);
expect(filteredSections).toStrictEqual([
{ ...sections.groups[1], options: [sections.groups[1].items[0]] },
]);
});
});

View file

@ -0,0 +1,41 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import type { LanguageDocumentationSections } from '../types';
import { elementToString } from './element_to_string';
export const getFilteredGroups = (
searchText: string,
searchInDescription?: boolean,
sections?: LanguageDocumentationSections,
numOfGroupsToOmit?: number
) => {
const normalizedSearchText = searchText.trim().toLocaleLowerCase();
return sections?.groups
.slice(numOfGroupsToOmit ?? 0)
.map((group) => {
const options = group.items.filter((helpItem) => {
return (
!normalizedSearchText ||
helpItem.label.toLocaleLowerCase().includes(normalizedSearchText) ||
// Converting the JSX element to a string first
(searchInDescription &&
elementToString(helpItem.description)
?.toLocaleLowerCase()
.includes(normalizedSearchText))
);
});
return { ...group, options };
})
.filter((group) => {
if (group.options.length > 0 || !normalizedSearchText) {
return true;
}
return group.label.toLocaleLowerCase().includes(normalizedSearchText);
});
};

View file

@ -5,6 +5,7 @@
"types": [
"jest",
"node",
"@emotion/react/types/css-prop",
]
},
"include": [

View file

@ -14,7 +14,6 @@ In order to enable text based languages on your unified search bar add `textBase
## Languages supported
- SQL: based on the Elasticsearch sql api
- ESQL: based on the Elastisearch esql api

View file

@ -5,10 +5,5 @@
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0",
"sideEffects": [
"*.scss"
],
"scripts": {
"make:docs": "ts-node --transpileOnly scripts/generate_esql_docs.ts",
"postmake:docs": "yarn run lint:fix",
"lint:fix": "cd ../.. && node ./scripts/eslint --fix ./packages/kbn-text-based-editor/src/inline_documentation/generated"
}
]
}

View file

@ -7,18 +7,25 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { memo, useState, useCallback, useEffect, useMemo } from 'react';
import React, { memo, useState, useCallback, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiText, EuiFlexGroup, EuiFlexItem, EuiCode } from '@elastic/eui';
import {
EuiText,
EuiFlexGroup,
EuiFlexItem,
EuiCode,
EuiButtonIcon,
EuiButtonEmpty,
} from '@elastic/eui';
import { Interpolation, Theme, css } from '@emotion/react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import {
LanguageDocumentationPopover,
type LanguageDocumentationSections,
LanguageDocumentationInline,
LanguageDocumentationFlyout,
} from '@kbn/language-documentation-popover';
import { getLimitFromESQLQuery } from '@kbn/esql-utils';
import { type MonacoMessage, getDocumentationSections } from '../helpers';
import { type MonacoMessage } from '../helpers';
import { ErrorsWarningsFooterPopover } from './errors_warnings_popover';
import { QueryHistoryAction, QueryHistory } from './query_history';
import { SubmitFeedbackComponent } from './feedback_component';
@ -43,8 +50,6 @@ interface EditorFooterProps {
updateQuery: (qs: string) => void;
isHistoryOpen: boolean;
setIsHistoryOpen: (status: boolean) => void;
isHelpMenuOpen: boolean;
setIsHelpMenuOpen: (status: boolean) => void;
measuredContainerWidth: number;
hideRunQueryText?: boolean;
editorIsInline?: boolean;
@ -52,6 +57,7 @@ interface EditorFooterProps {
hideTimeFilterInfo?: boolean;
hideQueryHistory?: boolean;
isInCompactMode?: boolean;
displayDocumentationAsFlyout?: boolean;
}
export const EditorFooter = memo(function EditorFooter({
@ -71,18 +77,15 @@ export const EditorFooter = memo(function EditorFooter({
setIsHistoryOpen,
hideQueryHistory,
isInCompactMode,
displayDocumentationAsFlyout,
measuredContainerWidth,
code,
isHelpMenuOpen,
setIsHelpMenuOpen,
}: EditorFooterProps) {
const kibana = useKibana<TextBasedEditorDeps>();
const { docLinks } = kibana.services;
const [isErrorPopoverOpen, setIsErrorPopoverOpen] = useState(false);
const [isLanguageComponentOpen, setIsLanguageComponentOpen] = useState(false);
const [isWarningPopoverOpen, setIsWarningPopoverOpen] = useState(false);
const [documentationSections, setDocumentationSections] =
useState<LanguageDocumentationSections>();
const onUpdateAndSubmit = useCallback(
(qs: string) => {
@ -98,17 +101,17 @@ export const EditorFooter = memo(function EditorFooter({
[runQuery, updateQuery]
);
const limit = useMemo(() => getLimitFromESQLQuery(code), [code]);
const toggleHistoryComponent = useCallback(() => {
setIsHistoryOpen(!isHistoryOpen);
setIsLanguageComponentOpen(false);
}, [isHistoryOpen, setIsHistoryOpen]);
useEffect(() => {
async function getDocumentation() {
const sections = await getDocumentationSections('esql');
setDocumentationSections(sections);
}
if (!documentationSections) {
getDocumentation();
}
}, [documentationSections]);
const toggleLanguageComponent = useCallback(async () => {
setIsLanguageComponentOpen(!isLanguageComponentOpen);
setIsHistoryOpen(false);
}, [isLanguageComponentOpen, setIsHistoryOpen]);
const limit = useMemo(() => getLimitFromESQLQuery(code), [code]);
return (
<EuiFlexGroup
@ -286,28 +289,25 @@ export const EditorFooter = memo(function EditorFooter({
</EuiFlexGroup>
</EuiFlexItem>
)}
{documentationSections && !editorIsInline && (
<EuiFlexItem grow={false}>
<LanguageDocumentationPopover
language="ES|QL"
sections={documentationSections}
{displayDocumentationAsFlyout && !Boolean(editorIsInline) && (
<>
<EuiButtonEmpty
iconType="documentation"
color="text"
data-test-subj="TextBasedLangEditor-documentation"
size="m"
onClick={() => toggleLanguageComponent()}
css={css`
cursor: pointer;
`}
/>
<LanguageDocumentationFlyout
searchInDescription
linkToDocumentation={docLinks?.links?.query?.queryESQL ?? ''}
buttonProps={{
color: 'text',
size: 'xs',
'data-test-subj': 'TextBasedLangEditor-documentation',
'aria-label': i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationLabel',
{
defaultMessage: 'Documentation',
}
),
}}
isHelpMenuOpen={isHelpMenuOpen}
onHelpMenuVisibilityChange={setIsHelpMenuOpen}
isHelpMenuOpen={isLanguageComponentOpen}
onHelpMenuVisibilityChange={setIsLanguageComponentOpen}
/>
</EuiFlexItem>
</>
)}
</EuiFlexGroup>
</EuiFlexItem>
@ -318,34 +318,14 @@ export const EditorFooter = memo(function EditorFooter({
<SubmitFeedbackComponent isSpaceReduced={true} />
{!hideQueryHistory && (
<QueryHistoryAction
toggleHistory={() => setIsHistoryOpen(!isHistoryOpen)}
toggleHistory={toggleHistoryComponent}
isHistoryOpen={isHistoryOpen}
isSpaceReduced={true}
/>
)}
{documentationSections && (
<EuiFlexItem grow={false}>
<LanguageDocumentationPopover
language="ES|QL"
sections={documentationSections}
searchInDescription
linkToDocumentation={docLinks?.links?.query?.queryESQL ?? ''}
buttonProps={{
color: 'text',
size: 'xs',
'data-test-subj': 'TextBasedLangEditor-documentation',
'aria-label': i18n.translate(
'textBasedEditor.query.textBasedLanguagesEditor.documentationLabel',
{
defaultMessage: 'Documentation',
}
),
}}
isHelpMenuOpen={isHelpMenuOpen}
onHelpMenuVisibilityChange={setIsHelpMenuOpen}
/>
</EuiFlexItem>
)}
<EuiFlexItem grow={false}>
<EuiButtonIcon iconType="documentation" onClick={toggleLanguageComponent} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</>
@ -362,6 +342,11 @@ export const EditorFooter = memo(function EditorFooter({
/>
</EuiFlexItem>
)}
{isLanguageComponentOpen && editorIsInline && (
<EuiFlexItem grow={false}>
<LanguageDocumentationInline searchInDescription />
</EuiFlexItem>
)}
</EuiFlexGroup>
);
});

View file

@ -161,43 +161,6 @@ export const parseErrors = (errors: Error[], code: string): MonacoMessage[] => {
});
};
export const getDocumentationSections = async (language: string) => {
const groups: Array<{
label: string;
description?: string;
items: Array<{ label: string; description?: JSX.Element }>;
}> = [];
if (language === 'esql') {
const {
sourceCommands,
processingCommands,
initialSection,
scalarFunctions,
aggregationFunctions,
groupingFunctions,
operators,
} = await import('./inline_documentation/esql_documentation_sections');
groups.push({
label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.esql', {
defaultMessage: 'ES|QL',
}),
items: [],
});
groups.push(
sourceCommands,
processingCommands,
scalarFunctions,
aggregationFunctions,
groupingFunctions,
operators
);
return {
groups,
initialSection,
};
}
};
export const getIndicesList = async (dataViews: DataViewsPublicPluginStart) => {
const indices = await dataViews.getIndices({
showAllIndices: false,

View file

@ -16,21 +16,6 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { TextBasedLanguagesEditor } from './text_based_languages_editor';
import type { TextBasedLanguagesEditorProps } from './types';
import { ReactWrapper } from 'enzyme';
jest.mock('./helpers', () => {
const module = jest.requireActual('./helpers');
return {
...module,
getDocumentationSections: () => ({
groups: [
{
label: 'How it works',
items: [],
},
],
}),
};
});
import { of } from 'rxjs';
describe('TextBasedLanguagesEditor', () => {
@ -133,9 +118,6 @@ describe('TextBasedLanguagesEditor', () => {
expect(
component!.find('[data-test-subj="TextBasedLangEditor-toggleWordWrap"]').length
).not.toBe(0);
expect(component!.find('[data-test-subj="TextBasedLangEditor-documentation"]').length).not.toBe(
0
);
});
it('should render the resize for the expanded code editor mode', async () => {
@ -156,6 +138,18 @@ describe('TextBasedLanguagesEditor', () => {
expect(component.find('[data-test-subj="TextBasedLangEditor-run-query"]').length).not.toBe(0);
});
it('should render the doc icon if the displayDocumentationAsFlyout is true', async () => {
const newProps = {
...props,
displayDocumentationAsFlyout: true,
editorIsInline: false,
};
const component = mount(renderTextBasedLanguagesEditorComponent({ ...newProps }));
expect(component.find('[data-test-subj="TextBasedLangEditor-documentation"]').length).not.toBe(
0
);
});
it('should not render the run query text if the hideRunQueryText prop is set to true', async () => {
const newProps = {
...props,

View file

@ -78,6 +78,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({
hideTimeFilterInfo,
hideQueryHistory,
hasOutline,
displayDocumentationAsFlyout,
}: TextBasedLanguagesEditorProps) {
const popoverRef = useRef<HTMLDivElement>(null);
const datePickerOpenStatusRef = useRef<boolean>(false);
@ -108,7 +109,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({
const [isHistoryOpen, setIsHistoryOpen] = useState(false);
const [isCodeEditorExpandedFocused, setIsCodeEditorExpandedFocused] = useState(false);
const [isLanguagePopoverOpen, setIsLanguagePopoverOpen] = useState(false);
const [isQueryLoading, setIsQueryLoading] = useState(true);
const [abortController, setAbortController] = useState(new AbortController());
@ -738,8 +738,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({
setIsHistoryOpen={toggleHistory}
measuredContainerWidth={measuredEditorWidth}
hideQueryHistory={hideHistoryComponent}
isHelpMenuOpen={isLanguagePopoverOpen}
setIsHelpMenuOpen={setIsLanguagePopoverOpen}
displayDocumentationAsFlyout={displayDocumentationAsFlyout}
/>
<ResizableButton
onMouseDownResizeHandler={onMouseDownResizeHandler}

View file

@ -61,6 +61,9 @@ export interface TextBasedLanguagesEditorProps {
/** adds border in the editor **/
hasOutline?: boolean;
/** adds a documentation icon in the footer which opens the inline docs as a flyout **/
displayDocumentationAsFlyout?: boolean;
}
export interface TextBasedEditorDeps {

View file

@ -25,7 +25,6 @@
"@kbn/data-views-plugin",
"@kbn/index-management-shared-types",
"@kbn/code-editor",
"@kbn/shared-ux-markdown",
"@kbn/fields-metadata-plugin",
"@kbn/esql-validation-autocomplete",
"@kbn/esql-utils",

View file

@ -36,7 +36,7 @@ describe('ESQLMenuPopover', () => {
renderESQLPopover();
expect(screen.getByTestId('esql-menu-button')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
expect(screen.getByTestId('esql-quick-reference')).toBeInTheDocument();
expect(screen.getByTestId('esql-examples')).toBeInTheDocument();
expect(screen.getByTestId('esql-about')).toBeInTheDocument();
expect(screen.getByTestId('esql-feedback')).toBeInTheDocument();

View file

@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useMemo, useState } from 'react';
import React, { useMemo, useState, useCallback } from 'react';
import {
EuiPopover,
EuiButton,
@ -19,6 +19,7 @@ import {
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { i18n } from '@kbn/i18n';
import { FEEDBACK_LINK } from '@kbn/esql-utils';
import { LanguageDocumentationFlyout } from '@kbn/language-documentation-popover';
import type { IUnifiedSearchPluginServices } from '../types';
export const ESQLMenuPopover = () => {
@ -26,15 +27,33 @@ export const ESQLMenuPopover = () => {
const { docLinks } = kibana.services;
const [isESQLMenuPopoverOpen, setIsESQLMenuPopoverOpen] = useState(false);
const [isLanguageComponentOpen, setIsLanguageComponentOpen] = useState(false);
const toggleLanguageComponent = useCallback(async () => {
setIsLanguageComponentOpen(!isLanguageComponentOpen);
setIsESQLMenuPopoverOpen(false);
}, [isLanguageComponentOpen]);
const esqlPanelItems = useMemo(() => {
const panelItems: EuiContextMenuPanelProps['items'] = [];
panelItems.push(
<EuiContextMenuItem
key="quickReference"
icon="documentation"
data-test-subj="esql-quick-reference"
onClick={() => toggleLanguageComponent()}
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.quickReference', {
defaultMessage: 'Quick Reference',
})}
</EuiContextMenuItem>,
<EuiContextMenuItem
key="about"
icon="iInCircle"
data-test-subj="esql-about"
target="_blank"
href={docLinks.links.query.queryESQL}
onClick={() => setIsESQLMenuPopoverOpen(false)}
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.documentation', {
defaultMessage: 'Documentation',
@ -46,6 +65,7 @@ export const ESQLMenuPopover = () => {
data-test-subj="esql-examples"
target="_blank"
href={docLinks.links.query.queryESQLExamples}
onClick={() => setIsESQLMenuPopoverOpen(false)}
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.documentation', {
defaultMessage: 'Example queries',
@ -58,6 +78,7 @@ export const ESQLMenuPopover = () => {
data-test-subj="esql-feedback"
target="_blank"
href={FEEDBACK_LINK}
onClick={() => setIsESQLMenuPopoverOpen(false)}
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.documentation', {
defaultMessage: 'Submit feedback',
@ -65,32 +86,44 @@ export const ESQLMenuPopover = () => {
</EuiContextMenuItem>
);
return panelItems;
}, [docLinks.links.query.queryESQL, docLinks.links.query.queryESQLExamples]);
}, [
docLinks.links.query.queryESQL,
docLinks.links.query.queryESQLExamples,
toggleLanguageComponent,
]);
return (
<EuiPopover
button={
<EuiButton
color="text"
onClick={() => setIsESQLMenuPopoverOpen(!isESQLMenuPopoverOpen)}
data-test-subj="esql-menu-button"
size="s"
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.label', {
defaultMessage: 'ES|QL help',
})}
</EuiButton>
}
panelProps={{
['data-test-subj']: 'esql-menu-popover',
css: { width: 240 },
}}
isOpen={isESQLMenuPopoverOpen}
closePopover={() => setIsESQLMenuPopoverOpen(false)}
panelPaddingSize="s"
display="block"
>
<EuiContextMenuPanel size="s" items={esqlPanelItems} />
</EuiPopover>
<>
<EuiPopover
button={
<EuiButton
color="text"
onClick={() => setIsESQLMenuPopoverOpen(!isESQLMenuPopoverOpen)}
data-test-subj="esql-menu-button"
size="s"
>
{i18n.translate('unifiedSearch.query.queryBar.esqlMenu.label', {
defaultMessage: 'ES|QL help',
})}
</EuiButton>
}
panelProps={{
['data-test-subj']: 'esql-menu-popover',
css: { width: 240 },
}}
isOpen={isESQLMenuPopoverOpen}
closePopover={() => setIsESQLMenuPopoverOpen(false)}
panelPaddingSize="s"
display="block"
>
<EuiContextMenuPanel size="s" items={esqlPanelItems} />
</EuiPopover>
<LanguageDocumentationFlyout
searchInDescription
linkToDocumentation={docLinks?.links?.query?.queryESQL ?? ''}
isHelpMenuOpen={isLanguageComponentOpen}
onHelpMenuVisibilityChange={setIsLanguageComponentOpen}
/>
</>
);
};

View file

@ -46,7 +46,8 @@
"@kbn/data-view-utils",
"@kbn/esql-utils",
"@kbn/react-kibana-mount",
"@kbn/field-utils"
"@kbn/field-utils",
"@kbn/language-documentation-popover"
],
"exclude": [
"target/**/*",

View file

@ -266,6 +266,7 @@ export const IndexDataVisualizerESQL: FC<IndexDataVisualizerESQLProps> = (dataVi
detectedTimestamp={currentDataView?.timeFieldName}
hideRunQueryText={false}
isLoading={queryHistoryStatus ?? false}
displayDocumentationAsFlyout
/>
<EuiFlexGroup gutterSize="m" direction={isWithinLargeBreakpoint ? 'column' : 'row'}>

View file

@ -198,6 +198,7 @@ export const EsqlQueryExpression: React.FC<
detectedTimestamp={detectedTimestamp}
hideRunQueryText={true}
isLoading={isLoading}
editorIsInline
hasOutline
/>
</EuiFormRow>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -7090,255 +7090,253 @@
"telemetry.usageCollectionConstant": "使用情况收集",
"telemetry.usageDataTitle": "使用情况收集",
"textBasedEditor.query.textBasedLanguagesEditor.aborted": "请求已中止",
"textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctions": "聚合函数",
"textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctionsDocumentationESQLDescription": "这些函数可以与 STATS...BY 搭配使用:",
"languageDocumentationPopover.documentationESQL.aggregationFunctions": "聚合函数",
"languageDocumentationPopover.documentationESQL.aggregationFunctionsDocumentationESQLDescription": "这些函数可以与 STATS...BY 搭配使用:",
"textBasedEditor.query.textBasedLanguagesEditor.cancel": "取消",
"textBasedEditor.query.textBasedLanguagesEditor.collapseLabel": "折叠",
"textBasedEditor.query.textBasedLanguagesEditor.commandsDescription": "源命令会生成一个表,其中通常包含来自 Elasticsearch 的数据。ES|QL 支持以下源命令。",
"languageDocumentationPopover.documentationESQL.commandsDescription": "源命令会生成一个表,其中通常包含来自 Elasticsearch 的数据。ES|QL 支持以下源命令。",
"textBasedEditor.query.textBasedLanguagesEditor.disableWordWrapLabel": "移除管道符上的换行符",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.abs": "ABS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.abs.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ABS\n 返回绝对值。\n\n ```\n ROW number = -1.0 \n | EVAL abs_number = ABS(number)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.acos": "ACOS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.acos.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ACOS\n 返回 `n` 的反余弦作为角度,以弧度表示。\n\n ```\n ROW a=.9\n | EVAL acos=ACOS(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.asin": "ASIN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.asin.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ASIN\n 返回输入数字表达式的反正弦\n 作为角度,以弧度表示。\n\n ```\n ROW a=.9\n | EVAL asin=ASIN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.atan": "ATAN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.atan.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ATAN\n 返回输入数字表达式的反正切\n 作为角度,以弧度表示。\n\n ```\n ROW a=12.9\n | EVAL atan=ATAN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.atan2": "ATAN2",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.atan2.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ATAN2\n 笛卡儿平面中正 x 轴\n 与从原点到点 (x , y) 构成的射线之间的角度,以弧度表示。\n\n ```\n ROW y=12.9, x=.6\n | EVAL atan2=ATAN2(y, x)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.autoBucketFunction": "BUCKET",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.autoBucketFunction.markdown": "### BUCKET\n用日期时间或数字输入创建值存储桶的分组。存储桶的大小可以直接提供或基于建议的计数和值范围进行选择。\n\n`BUCKET` 以两种模式运行:\n\n1.在此模式下基于存储桶计数建议(四个参数)和范围计算存储桶的大小。\n2.在此模式下直接提供存储桶大小(两个参数)。\n\n使用存储桶的目标数量、起始范围和结束范围`BUCKET` 将选取适当的存储桶大小以生成目标数量或更小数量的存储桶。\n\n例如一年请求多达 20 个存储桶会按每月时间间隔组织数据:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hire_date = MV_SORT(VALUES(hire_date)) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT hire_date\n```\n\n**注意**:目标并不是提供存储桶的确切目标数量,而是选择一个范围,最多提供存储桶的目标数量。\n\n可以组合 `BUCKET` 与聚合以创建直方图:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_month = COUNT(*) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT month\n```\n\n**注意**`BUCKET` 不会创建未匹配任何文档的存储桶。因此,上一示例缺少 `1985-03-01` 和其他日期。\n\n如果需要更多存储桶可能导致更小的范围。例如如果一年内最多请求 100 个存储桶,会导致周期为周的存储桶:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 100, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT week\n```\n\n**注意**`AUTO_BUCKET` 不筛选任何行。它只会使用提供的范围来选取适当的存储桶大小。对于值超出范围的行,它会返回与超出范围的存储桶对应的存储桶值。组合 `BUCKET` 与 `WHERE` 可筛选行。\n\n如果提前已知所需存储桶大小则只需提供它作为第二个参数而忽略范围\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 1 week)\n| SORT week\n```\n\n**注意**:提供存储桶大小作为第二个参数时,它必须为持续时间或日期期间。\n\n`BUCKET` 还可对数字字段执行操作。例如,要创建工资直方图:\n\n```\nFROM employees\n| STATS COUNT(*) by bs = BUCKET(salary, 20, 25324, 74999)\n| SORT bs\n```\n\n与前面的有意筛选日期范围示例不同您极少想要筛选数值范围。您必须分别查找最小值和最大值。ES|QL 尚未提供简便方法来自动执行此操作。\n\n如果提前已知所需存储桶大小则可以忽略该范围。只需提供它作为第二个参数即可\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS c = COUNT(1) BY b = BUCKET(salary, 5000.)\n| SORT b\n```\n\n**注意**:提供存储桶大小作为第二个参数时,它必须为 **浮点类型**。\n\n这里提供了一个示例用于为过去 24 小时创建小时存储桶,并计算每小时的事件数:\n\n```\nFROM sample_data\n| WHERE @timestamp >= NOW() - 1 day and @timestamp < NOW()\n| STATS COUNT(*) BY bucket = BUCKET(@timestamp, 25, NOW() - 1 day, NOW())\n```\n\n这里提供了一个示例用于为 1985 年创建月度存储桶,并按聘用月份计算平均工资:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS AVG(salary) BY bucket = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT bucket\n```\n\n`BUCKET` 可用在 `STATS …​ BY …` 命令的聚合和分组部分, 前提是在聚合部分中,该函数 **由在分组部分中定义的别名引用**,或使用完全相同的表达式调用。\n\n例如\n\n```\nFROM employees\n| STATS s1 = b1 + 1, s2 = BUCKET(salary / 1000 + 999, 50.) + 2 BY b1 = BUCKET(salary / 100 + 99, 50.), b2 = BUCKET(salary / 1000 + 999, 50.)\n| SORT b1, b2\n| KEEP s1, b1, s2, b2\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.binaryOperators": "二进制运算符",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.binaryOperators.markdown": "### 二进制运算符\n支持这些二进制比较运算符\n\n* 等于:`==`\n* 不等于:`!=`\n* 小于:`<`\n* 小于或等于:`<=`\n* 大于:`>`\n* 大于或等于:`>=`\n* 加:`+`\n* 减:`-`\n* 乘:`*`\n* 除:`/`\n* 取模:`%`\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.booleanOperators": "布尔运算符",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.booleanOperators.markdown": "### 布尔运算符\n支持以下布尔运算符\n\n* `AND`\n* `OR`\n* `NOT`\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.bucket": "BUCKET",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.bucket.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### BUCKET\n 用日期时间或数字输入创建值(存储桶)的分组。\n 存储桶的大小可以直接提供,或基于建议的计数和值范围进行选择。\n\n ```\n FROM employees\n | WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n | STATS hire_date = MV_SORT(VALUES(hire_date)) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n | SORT hire_date\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.case": "CASE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.case.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CASE\n 接受成对的条件和值。此函数返回属于第一个\n 评估为 `true` 的条件的值。\n\n 如果参数数量为奇数,则最后一个参数为\n 在无条件匹配时返回的默认值。如果参数数量为偶数,且\n 无任何条件匹配,则此函数返回 `null`。\n\n ```\n FROM employees\n | EVAL type = CASE(\n languages <= 1, \"monolingual\",\n languages <= 2, \"bilingual\",\n \"polyglot\")\n | KEEP emp_no, languages, type\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.castOperator": "Cast (::)",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.castOperator.markdown": "### CAST (`::`)\n`::` 运算符为 `TO_<type>` 类型转换函数提供了实用的替代语法。\n\n例如\n```\nROW ver = CONCAT((\"0\"::INT + 1)::STRING, \".2.3\")::VERSION\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cbrt": "CBRT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cbrt.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CBRT\n 返回数字的立方根。输入可以为任何数字值,返回值始终为双精度值。\n 无穷大的立方根为 null。\n\n ```\n ROW d = 1000.0\n | EVAL c = cbrt(d)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ceil": "CEIL",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ceil.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CEIL\n 将数字四舍五入为最近的整数。\n\n ```\n ROW a=1.8\n | EVAL a=CEIL(a)\n ```\n 注意:对于 `long`(包括无符号值)和 `integer`,这相当于“无操作”。对于 `double`,这会提取最接近整数的 `double` 值,类似于 Math.ceil。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cidr_match": "CIDR_MATCH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cidr_match.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CIDR_MATCH\n 如果提供的 IP 包含在所提供的其中一个 CIDR 块中,则返回 true。\n\n ```\n FROM hosts \n | WHERE CIDR_MATCH(ip1, \"127.0.0.2/32\", \"127.0.0.3/32\") \n | KEEP card, host, ip0, ip1\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.coalesce": "COALESCE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.coalesce.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COALESCE\n 返回它的第一个不为 null 的参数。如果所有参数均为 null则返回 `null`。\n\n ```\n ROW a=null, b=\"b\"\n | EVAL COALESCE(a, b)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.concat": "CONCAT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.concat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CONCAT\n 串联两个或多个字符串。\n\n ```\n FROM employees\n | KEEP first_name, last_name\n | EVAL fullname = CONCAT(first_name, \" \", last_name)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cos": "COS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cos.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COS\n 返回角度的余弦。\n\n ```\n ROW a=1.8 \n | EVAL cos=COS(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cosh": "COSH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cosh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COSH\n 返回角度的双曲余弦。\n\n ```\n ROW a=1.8 \n | EVAL cosh=COSH(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_diff": "DATE_DIFF",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_diff.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_DIFF\n 从 `endTimestamp` 中减去 `startTimestamp`,并以倍数 `unit` 返回差异。\n 如果 `startTimestamp` 晚于 `endTimestamp`,则返回负值。\n\n ```\n ROW date1 = TO_DATETIME(\"2023-12-02T11:00:00.000Z\"), date2 = TO_DATETIME(\"2023-12-02T11:00:00.001Z\")\n | EVAL dd_ms = DATE_DIFF(\"microseconds\", date1, date2)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_extract": "DATE_EXTRACT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_extract.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_EXTRACT\n 提取日期的某些部分,如年、月、日、小时。\n\n ```\n ROW date = DATE_PARSE(\"yyyy-MM-dd\", \"2022-05-06\")\n | EVAL year = DATE_EXTRACT(\"year\", date)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_format": "DATE_FORMAT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_format.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_FORMAT\n 以提供的格式返回日期的字符串表示形式。\n\n ```\n FROM employees\n | KEEP first_name, last_name, hire_date\n | EVAL hired = DATE_FORMAT(\"YYYY-MM-dd\", hire_date)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_parse": "DATE_PARSE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_parse.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_PARSE\n 通过使用在第一个参数中指定的格式来解析第二个参数,从而返回日期。\n\n ```\n ROW date_string = \"2022-05-06\"\n | EVAL date = DATE_PARSE(\"yyyy-MM-dd\", date_string)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_trunc": "DATE_TRUNC",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.date_trunc.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_TRUNC\n 将日期向下舍入到最近的时间间隔。\n\n ```\n FROM employees\n | KEEP first_name, last_name, hire_date\n | EVAL year_hired = DATE_TRUNC(1 year, hire_date)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dissect": "DISSECT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dissect.markdown": "### DISSECT\n使用 `DISSECT`,您可以从字符串中提取结构化数据。`DISSECT` 将根据基于分隔符的模式来匹配字符串,并提取指定键作为列。\n\n请参阅[分解处理器文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/dissect-processor.html)了解分解模式的语法。\n\n```\nROW a = \"1953-01-23T12:15:00Z - some text - 127.0.0.1\"\n| DISSECT a \"%'{Y}-%{M}-%{D}T%{h}:%{m}:%{s}Z - %{msg} - %{ip}'\"\n``` ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.drop": "DROP",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.drop.markdown": "### DROP\n使用 `DROP` 可从表中移除列:\n \n```\nFROM employees\n| DROP height\n```\n\n您不必按名称指定每个列而可以使用通配符丢弃名称匹配某种模式的所有列\n\n```\nFROM employees\n| DROP height*\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.e": "E",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.e.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### E\n 返回 Euler 函数的编号。\n\n ```\n ROW E()\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ends_with": "ENDS_WITH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ends_with.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ENDS_WITH\n 返回布尔值,指示关键字字符串是否以另一个字符串结尾。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_E = ENDS_WITH(last_name, \"d\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.enrich": "ENRICH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.enrich.markdown": "### ENRICH\n您可以使用 `ENRICH` 将来自现有索引的数据添加到传入记录中。它类似于[采集扩充](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html),但作用于查询时间。\n\n```\nROW language_code = \"1\"\n| ENRICH languages_policy\n```\n\n执行 `ENRICH` 需要[扩充策略](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html#enrich-policy)。扩充策略定义一个匹配字段(键字段)和一组扩充字段。\n\n`ENRICH` 将根据匹配字段值在[扩充索引](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html#enrich-index)中查找记录。输入数据集中的匹配键可以使用 `ON <field-name>` 来定义;如果未指定,将对字段名称与在扩充策略中定义的匹配字段相同的字段执行匹配。\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a\n```\n\n您可以使用 `WITH <field1>, <field2>...` 语法指定必须将哪些属性(在那些在策略中定义为扩充字段的字段之间)添加到结果中。\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a WITH language_name\n```\n\n还可以使用 `WITH new_name=<field1>` 重命名属性\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a WITH name = language_name\n```\n\n默认情况下如果未定义任何 `WITH``ENRICH` 会将在扩充策略中定义的所有扩充字段添加到结果中。\n\n如果出现名称冲突新创建的字段将覆盖现有字段。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eval": "EVAL",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eval.markdown": "### EVAL\n`EVAL` 允许您添加新列:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| EVAL height_feet = height * 3.281, height_cm = height * 100\n```\n\n如果指定列已存在将丢弃现有列并将新列追加到表后面\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| EVAL height = height * 3.281\n```\n\n#### 函数\n`EVAL` 支持各种用于计算值的函数。请参阅“函数”了解更多信息。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.floor": "FLOOR",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.floor.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### FLOOR\n 将数字向下舍入到最近的整数。\n\n ```\n ROW a=1.8\n | EVAL a=FLOOR(a)\n ```\n 注意:对于 `long`(包括无符号值)和 `integer`,这相当于“无操作”。\n 对于 `double`,这会提取最接近整数的 `double` 值,\n 类似于 Math.floor。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from": "FROM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from_base64": "FROM_BASE64",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from_base64.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### FROM_BASE64\n 解码 base64 字符串。\n\n ```\n row a = \"ZWxhc3RpYw==\" \n | eval d = from_base64(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from.markdown": "### FROM\n`FROM` 源命令返回一个表,其中最多包含 10,000 个来自数据流、索引或别名的文档。生成的表中的每一行代表一个文档。每一列对应一个字段,并可以通过该字段的名称进行访问。\n\n```\nFROM employees\n```\n\n您可以使用[日期数学表达式](https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#api-date-math-index-names)来引用索引、别名和数据流。这可能对时间序列数据非常有用。\n\n使用逗号分隔列表或通配符可查询多个数据流、索引或别名\n\n```\nFROM employees-00001,employees-*\n```\n\n#### 元数据\n\nES|QL 可访问以下元数据字段:\n\n* `_index`:文档所属的索引。字段类型为 `keyword`.\n* `_id`:源文档的 ID。字段类型为 `keyword`.\n* `_version`:源文档的版本。字段类型为 `long`。\n\n使用 `METADATA` 指令可启用元数据字段:\n\n```\nFROM index [METADATA _index, _id]\n```\n\n元数据字段仅在数据源为索引时可用。因此`FROM` 是唯一支持 `METADATA` 指令的源命令。\n\n启用后这些字段将可用于后续处理命令就像其他索引字段一样\n\n```\nFROM ul_logs, apps [METADATA _index, _version]\n| WHERE id IN (13, 14) AND _version == 1\n| EVAL key = CONCAT(_index, \"_\", TO_STR(id))\n| SORT id, _index\n| KEEP id, _index, _version, key\n```\n\n此外与索引字段类似一旦执行了聚合后续命令将无法再访问元数据字段除非它用作分组字段\n\n```\nFROM employees [METADATA _index, _id]\n| STATS max = MAX(emp_no) BY _index\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.greatest": "GREATEST",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.greatest.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### GREATEST\n 返回多个列中的最大值。除了可一次对多个列运行以外,\n 此函数与 `MV_MAX` 类似。\n\n ```\n ROW a = 10, b = 20\n | EVAL g = GREATEST(a, b)\n ```\n 注意:对 `keyword` 或 `text` 字段运行时,此函数将按字母顺序返回最后一个字符串。对 `boolean` 列运行时,如果任何值为 `true`,此函数将返回 `true`。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.grok": "GROK",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.grok.markdown": "### GROK\n使用 `GROK`,您可以从字符串中提取结构化数据。`GROK` 将基于正则表达式根据模式来匹配字符串,并提取指定模式作为列。\n\n请参阅 [grok 处理器文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/grok-processor.html)了解 grok 模式的语法。\n\n```\nROW a = \"12 15.5 15.6 true\"\n| GROK a \"%'{NUMBER:b:int}' %'{NUMBER:c:float}' %'{NUMBER:d:double}' %'{WORD:e:boolean}'\"\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.inOperator": "IN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.inOperator.markdown": "### IN\n`IN` 运算符允许测试字段或表达式是否等于文本、字段或表达式列表中的元素:\n\n```\nROW a = 1, b = 4, c = 3\n| WHERE c-a IN (3, b / 2, a)\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ip_prefix": "IP_PREFIX",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ip_prefix.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### IP_PREFIX\n 截短 IP 至给定的前缀长度。\n\n ```\n row ip4 = to_ip(\"1.2.3.4\"), ip6 = to_ip(\"fe80::cae2:65ff:fece:feb9\")\n | eval ip4_prefix = ip_prefix(ip4, 24, 0), ip6_prefix = ip_prefix(ip6, 0, 112);\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.keep": "KEEP",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.keep.markdown": "### KEEP\n使用 `KEEP` 命令,您可以指定将返回哪些列以及返回这些列的顺序。\n\n要限制返回的列数请使用列名的逗号分隔列表。将按指定顺序返回这些列\n \n```\nFROM employees\n| KEEP first_name, last_name, height\n```\n\n您不必按名称指定每个列而可以使用通配符返回名称匹配某种模式的所有列\n\n```\nFROM employees\n| KEEP h*\n```\n\n星号通配符 (`*`) 自身将转换为不与其他参数匹配的所有列。此查询将首先返回所有名称以 h 开头的所有列,随后返回所有其他列:\n\n```\nFROM employees\n| KEEP h*, *\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.least": "LEAST",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.least.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LEAST\n 返回多个列中的最小值。除了可一次对多个列运行以外,此函数与 `MV_MIN` 类似。\n\n ```\n ROW a = 10, b = 20\n | EVAL l = LEAST(a, b)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.left": "LEFT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.left.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LEFT\n 返回从“字符串”中提取“长度”字符的子字符串,从左侧开始。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL left = LEFT(last_name, 3)\n | SORT last_name ASC\n | LIMIT 5\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.length": "LENGTH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.length.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LENGTH\n 返回字符串的字符长度。\n\n ```\n FROM employees\n | KEEP first_name, last_name\n | EVAL fn_length = LENGTH(first_name)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.limit": "LIMIT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.limit.markdown": "### LIMIT\n`LIMIT` 处理命令允许您限制行数:\n \n```\nFROM employees\n| LIMIT 5\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.locate": "LOCATE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.locate.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOCATE\n 返回一个整数,指示关键字子字符串在另一字符串中的位置\n\n ```\n row a = \"hello\"\n | eval a_ll = locate(a, \"ll\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.log": "LOG",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.log.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOG\n 以某底数返回值的对数。输入可以为任何数字值,返回值始终为双精度值。\n\n 求零、负数的对数,以及底数为一时将返回 `null`,并显示警告。\n\n ```\n ROW base = 2.0, value = 8.0\n | EVAL s = LOG(base, value)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.log10": "LOG10",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.log10.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOG10\n 以底数 10 返回值的对数。输入可以为任何数字值,返回值始终为双精度值。\n\n 求 0 和负数的对数时将返回 `null`,并显示警告。\n\n ```\n ROW d = 1000.0 \n | EVAL s = LOG10(d)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ltrim": "LTRIM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.ltrim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LTRIM\n 从字符串中移除前导空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = LTRIM(message)\n | EVAL color = LTRIM(color)\n | EVAL message = CONCAT(\"'\", message, \"'\")\n | EVAL color = CONCAT(\"'\", color, \"'\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.markdown": "## ES|QL\n\nES|QLElasticsearch 查询语言)查询包含一系列命令,它们用管道字符分隔:`|`。每个查询以**源命令**开头,它会生成一个表,其中通常包含来自 Elasticsearch 的数据。\n\n源命令可后接一个或多个**处理命令**。处理命令可通过添加、移除以及更改行和列来更改前一个命令的输出表。\n\n```\nsource-command\n| processing-command1\n| processing-command2\n```\n\n查询的结果为由最后的处理命令生成的表。 \n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_append": "MV_APPEND",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_append.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_APPEND\n 串联两个多值字段的值。\n\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_avg": "MV_AVG",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_avg.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_AVG\n 将多值字段转换为包含所有值的平均值的单值字段。\n\n ```\n ROW a=[3, 5, 1, 6]\n | EVAL avg_a = MV_AVG(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_concat": "MV_CONCAT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_concat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_CONCAT\n 将多值字符串表达式转换为单值列,其中包含由分隔符分隔的所有值的串联形式。\n\n ```\n ROW a=[\"foo\", \"zoo\", \"bar\"]\n | EVAL j = MV_CONCAT(a, \", \")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_count": "MV_COUNT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_count.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_COUNT\n 将多值表达式转换为包含值计数的单值列。\n\n ```\n ROW a=[\"foo\", \"zoo\", \"bar\"]\n | EVAL count_a = MV_COUNT(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_dedupe": "MV_DEDUPE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_dedupe.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_DEDUPE\n 移除多值字段中的重复值。\n\n ```\n ROW a=[\"foo\", \"foo\", \"bar\", \"foo\"]\n | EVAL dedupe_a = MV_DEDUPE(a)\n ```\n 注意:`MV_DEDUPE` 可能但不会始终对列中的值进行排序。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_first": "MV_FIRST",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_first.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_FIRST\n 将多值表达式转换为包含第一个值的\n 单值列。这在从按已知顺序发出多值列的\n 函数(如 `SPLIT`)中读取数据时尤其有用。\n\n 无法保证从底层存储\n 读取多值字段的顺序。它 *通常* 为升序,但不应\n 依赖于此。如果需要最小值,请使用 `MV_MIN` 而不是\n `MV_FIRST`。`MV_MIN` 针对排序值进行了优化,因此\n 对 `MV_FIRST` 没有性能优势。\n\n ```\n ROW a=\"foo;bar;baz\"\n | EVAL first_a = MV_FIRST(SPLIT(a, \";\"))\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_last": "MV_LAST",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_last.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_LAST\n 将多值表达式转换为包含最后一个值的单值\n 列。这在从按已知顺序发出多值列的函数\n (如 `SPLIT`)中读取数据时尤其有用。\n\n 无法保证从底层存储\n 读取多值字段的顺序。它 *通常* 为升序,但不应\n 依赖于此。如果需要最大值,请使用 `MV_MAX` 而不是\n `MV_LAST`。`MV_MAX` 针对排序值进行了优化,因此\n 对 `MV_LAST` 没有性能优势。\n\n ```\n ROW a=\"foo;bar;baz\"\n | EVAL last_a = MV_LAST(SPLIT(a, \";\"))\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_max": "MV_MAX",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_max.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MAX\n 将多值表达式转换为包含最大值的单值列。\n\n ```\n ROW a=[3, 5, 1]\n | EVAL max_a = MV_MAX(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_median": "MV_MEDIAN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_median.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MEDIAN\n 将多值字段转换为包含中位数值的单值字段。\n\n ```\n ROW a=[3, 5, 1]\n | EVAL median_a = MV_MEDIAN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_min": "MV_MIN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_min.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MIN\n 将多值表达式转换为包含最小值的单值列。\n\n ```\n ROW a=[2, 1]\n | EVAL min_a = MV_MIN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_slice": "MV_SLICE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_slice.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SLICE\n 使用起始和结束索引值返回多值字段的子集。\n\n ```\n row a = [1, 2, 2, 3]\n | eval a1 = mv_slice(a, 1), a2 = mv_slice(a, 2, 3)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_sort": "MV_SORT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_sort.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SORT\n 按字典顺序对多值字段排序。\n\n ```\n ROW a = [4, 2, -3, 2]\n | EVAL sa = mv_sort(a), sd = mv_sort(a, \"DESC\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_sum": "MV_SUM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_sum.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SUM\n 将多值字段转换为包含所有值的总和的单值字段。\n\n ```\n ROW a=[3, 5, 6]\n | EVAL sum_a = MV_SUM(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_zip": "MV_ZIP",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mv_zip.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_ZIP\n 组合两个使用分隔符联接在一起的多值字段中的值。\n\n ```\n ROW a = [\"x\", \"y\", \"z\"], b = [\"1\", \"2\"]\n | EVAL c = mv_zip(a, b, \"-\")\n | KEEP a, b, c\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvExpand": "MV_EXPAND",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvExpand.markdown": "### MV_EXPAND\n`MV_EXPAND` 处理命令将多值字段扩展成每个值一行,从而复制其他字段: \n```\nROW a=[1,2,3], b=\"b\", j=[\"a\",\"b\"]\n| MV_EXPAND a\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.now": "NOW",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.now.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### NOW\n 返回当前日期和时间。\n\n ```\n ROW current_date = NOW()\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.pi": "PI",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.pi.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### PI\n 返回 Pi即圆的周长与其直径的比率。\n\n ```\n ROW PI()\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.pow": "POW",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.pow.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### POW\n 返回提升为 `exponent` 幂的 `base` 的值。\n\n ```\n ROW base = 2.0, exponent = 2\n | EVAL result = POW(base, exponent)\n ```\n 注意:此处仍可能使双精度结果溢出;在该情况下,将返回 null。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.predicates": "Null 值",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.predicates.markdown": "### NULL 值\n对于 NULL 比较,请使用 `IS NULL` 和 `IS NOT NULL` 谓词:\n\n```\nFROM employees\n| WHERE birth_date IS NULL\n| KEEP first_name, last_name\n| SORT first_name\n| LIMIT 3\n```\n\n```\nFROM employees\n| WHERE is_rehired IS NOT NULL\n| STATS count(emp_no)\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rename": "RENAME",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rename.markdown": "### RENAME\n请使用 `RENAME` 通过以下语法对列重命名:\n\n```\nRENAME <old-name> AS <new-name>\n```\n\n例如\n\n```\nFROM employees\n| KEEP first_name, last_name, still_hired\n| RENAME still_hired AS employed\n```\n\n如果使用新名称的列已存在将用新列替换该列。\n\n可以使用单个 `RENAME` 命令对多个列重命名:\n\n```\nFROM employees\n| KEEP first_name, last_name\n| RENAME first_name AS fn, last_name AS ln\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.repeat": "REPEAT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.repeat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### REPEAT\n 返回通过串联 `string` 自身与指定次数 `number` 构造而成的字符串。\n\n ```\n ROW a = \"Hello!\"\n | EVAL triple_a = REPEAT(a, 3);\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.replace": "REPLACE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.replace.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### REPLACE\n 此函数将字符串 `str` 中正则表达式 `regex` 的任何匹配项\n 替换为替代字符串 `newStr`。\n\n ```\n ROW str = \"Hello World\"\n | EVAL str = REPLACE(str, \"World\", \"Universe\")\n | KEEP str\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.right": "RIGHT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.right.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### RIGHT\n 返回从“字符串”中提取“长度”字符的子字符串,从右侧开始。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL right = RIGHT(last_name, 3)\n | SORT last_name ASC\n | LIMIT 5\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.round": "ROUND",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.round.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ROUND\n 将数字舍入到指定小数位数。\n 默认值为 0即返回最近的整数。如果\n 精确度为负数,则将数字舍入到\n 小数点左侧的位数。\n\n ```\n FROM employees\n | KEEP first_name, last_name, height\n | EVAL height_ft = ROUND(height * 3.281, 1)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.row": "ROW",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.row.markdown": "### ROW\n`ROW` 源命令会生成一个行,其中包含一个或多个含有您指定的值的列。这可以用于测试。\n \n```\nROW a = 1, b = \"two\", c = null\n```\n\n请使用方括号创建多值列\n\n```\nROW a = [2, 1]\n```\n\nROW 支持使用函数:\n\n```\nROW a = ROUND(1.23, 0)\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rtrim": "RTRIM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rtrim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### RTRIM\n 从字符串中移除尾随空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = RTRIM(message)\n | EVAL color = RTRIM(color)\n | EVAL message = CONCAT(\"'\", message, \"'\")\n | EVAL color = CONCAT(\"'\", color, \"'\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.show": "SHOW",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.show.markdown": "### SHOW\n`SHOW <item>` 源命令返回有关部署及其功能的信息:\n\n* 使用 `SHOW INFO` 可返回部署的版本、构建日期和哈希。\n* 使用 `SHOW FUNCTIONS` 可返回所有受支持函数的列表和每个函数的概要。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.signum": "SIGNUM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.signum.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SIGNUM\n 返回给定数字的符号。\n 它对负数返回 `-1`,对 `0` 返回 `0`,对正数返回 `1`。\n\n ```\n ROW d = 100.0\n | EVAL s = SIGNUM(d)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sin": "SIN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sin.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SIN\n 返回角度的正弦三角函数。\n\n ```\n ROW a=1.8 \n | EVAL sin=SIN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sinh": "SINH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sinh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SINH\n 返回角度的双曲正弦。\n\n ```\n ROW a=1.8 \n | EVAL sinh=SINH(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sort": "SORT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sort.markdown": "### SORT\n使用 `SORT` 命令可对一个或多个字段上的行排序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height\n```\n\n默认排序顺序为升序。请使用 `ASC` 或 `DESC` 设置显式排序顺序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height DESC\n```\n\n如果两个行具有相同的排序键则保留原始顺序。您可以提供其他排序表达式充当连接断路器\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height DESC, first_name ASC\n```\n\n#### `null` 值\n默认情况下会将 `null` 值视为大于任何其他值。使用升序排序顺序时,会最后对 `null` 值排序,而使用降序排序顺序时,会首先对 `null` 值排序。您可以通过提供 `NULLS FIRST` 或 `NULLS LAST` 来更改该排序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT first_name ASC NULLS FIRST\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.split": "SPLIT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.split.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SPLIT\n 将单值字符串拆分成多个字符串。\n\n ```\n ROW words=\"foo;bar;baz;qux;quux;corge\"\n | EVAL word = SPLIT(words, \";\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sqrt": "SQRT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sqrt.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SQRT\n 返回数字的平方根。输入可以为任何数字值,返回值始终为双精度值。\n 负数和无穷大的平方根为 null。\n\n ```\n ROW d = 100.0\n | EVAL s = SQRT(d)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_contains": "ST_CONTAINS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_contains.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_CONTAINS\n 返回第一个几何形状是否包含第二个几何形状。\n 这是 `ST_WITHIN` 函数的反向函数。\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_CONTAINS(city_boundary, TO_GEOSHAPE(\"POLYGON((109.35 18.3, 109.45 18.3, 109.45 18.4, 109.35 18.4, 109.35 18.3))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_disjoint": "ST_DISJOINT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_disjoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_DISJOINT\n 返回两个几何图形或几何图形列是否不相交。\n 这是 `ST_INTERSECTS` 函数的反向函数。\n 从数学上讲ST_Disjoint(A, B) ⇔ A ⋂ B = ∅\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_DISJOINT(city_boundary, TO_GEOSHAPE(\"POLYGON((-10 -60, 120 -60, 120 60, -10 60, -10 -60))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_distance": "ST_DISTANCE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_distance.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_DISTANCE\n 计算两点之间的距离。\n 对于笛卡尔几何形状,这是以相同单位作为原始坐标时的毕达哥拉斯距离。\n 对于地理几何形状而言,这是沿着地球大圆的圆周距离(以米为单位)。\n\n ```\n FROM airports\n | WHERE abbrev == \"CPH\"\n | EVAL distance = ST_DISTANCE(location, city_location)\n | KEEP abbrev, name, location, city_location, distance\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_intersects": "ST_INTERSECTS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_intersects.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_INTERSECTS\n 如果两个几何形状相交,则返回 true。\n 如果它们有任何共同点,包括其内点\n (沿线的点或多边形内的点),则表示它们相交。\n 这是 `ST_DISJOINT` 函数的反向函数。\n 从数学上讲ST_Intersects(A, B) ⇔ A ⋂ B ≠ ∅\n\n ```\n FROM airports\n | WHERE ST_INTERSECTS(location, TO_GEOSHAPE(\"POLYGON((42 14, 43 14, 43 15, 42 15, 42 14))\"))\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_within": "ST_WITHIN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_within.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_WITHIN\n 返回第一个几何形状是否在第二个几何形状内。\n 这是 `ST_CONTAINS` 函数的反向函数。\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_WITHIN(city_boundary, TO_GEOSHAPE(\"POLYGON((109.1 18.15, 109.6 18.15, 109.6 18.65, 109.1 18.65, 109.1 18.15))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_x": "ST_X",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_x.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_X\n 从提供的点中提取 `x` 坐标。\n 如果点的类型为 `geo_point`,则这等同于提取 `longitude` 值。\n\n ```\n ROW point = TO_GEOPOINT(\"POINT(42.97109629958868 14.7552534006536)\")\n | EVAL x = ST_X(point), y = ST_Y(point)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_y": "ST_Y",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.st_y.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_Y\n 从提供的点中提取 `y` 坐标。\n 如果点的类型为 `geo_point`,则这等同于提取 `latitude` 值。\n\n ```\n ROW point = TO_GEOPOINT(\"POINT(42.97109629958868 14.7552534006536)\")\n | EVAL x = ST_X(point), y = ST_Y(point)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.starts_with": "STARTS_WITH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.starts_with.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### STARTS_WITH\n 返回指示关键字字符串是否以另一个字符串开头的布尔值。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_S = STARTS_WITH(last_name, \"B\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.statsby": "STATS ...BY",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.statsby.markdown": "### STATS ...BY\n使用 `STATS ...BY` 可根据公共值对行分组,并计算已分组行中的一个或多个聚合值。\n\n**示例**\n\n```\nFROM employees\n| STATS count = COUNT(emp_no) BY languages\n| SORT languages\n```\n\n如果省略 `BY`,输出表实际将包含一行,其中为应用于整个数据集的聚合:\n\n```\nFROM employees\n| STATS avg_lang = AVG(languages)\n```\n\n可以计算多个值\n\n```\nFROM employees\n| STATS avg_lang = AVG(languages), max_lang = MAX(languages)\n```\n\n也可以按多个值分组仅长整型和关键字家族字段支持\n\n```\nFROM employees\n| EVAL hired = DATE_FORMAT(hire_date, \"YYYY\")\n| STATS avg_salary = AVG(salary) BY hired, languages.long\n| EVAL avg_salary = ROUND(avg_salary)\n| SORT hired, languages.long\n```\n\n请参阅**聚合函数**获取可与 `STATS ...BY` 搭配使用的函数列表。\n\n聚合函数和分组表达式均接受其他函数。这在对多值列使用 `STATS...BY` 时有用。例如,要计算平均工资变动,可以首先使用 `MV_AVG` 对每名员工的多个值求平均值,然后将结果用于 `AVG` 函数:\n\n```\nFROM employees\n| STATS avg_salary_change = AVG(MV_AVG(salary_change))\n```\n\n按表达式分组的示例为根据员工姓氏的第一个字母对其进行分组\n\n```\nFROM employees\n| STATS my_count = COUNT() BY LEFT(last_name, 1)\n| SORT `LEFT(last_name, 1)`\n```\n\n指定输出列名称为可选操作。如果未指定新列名称等于该表达式。以下查询将返回名为 `AVG(salary)` 的列:\n\n```\nFROM employees\n| STATS AVG(salary)\n```\n\n由于此名称包含特殊字符在后续命令中使用该名称时需要用反撇号 (`) 引用它:\n\n```\nFROM employees\n| STATS AVG(salary)\n| EVAL avg_salary_rounded = ROUND(`AVG(salary)`)\n```\n\n**注意**:不包含任何组的 `STATS` 比添加组更快。\n\n**注意**:当前,根据单一表达式进行分组比根据许多表达式进行分组更为优化。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.stringOperators": "LIKE 和 RLIKE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.stringOperators.markdown": "### LIKE 和 RLIKE\n使用通配符或正则表达式比较字符串时请使用 `LIKE` 或 `RLIKE`\n\n使用 `LIKE` 时,可使用通配符来匹配字符串。支持以下通配符字符:\n\n* `*` 匹配零个或更多字符。\n* `?` 匹配一个字符。\n\n```\nFROM employees\n| WHERE first_name LIKE \"?b*\"\n| KEEP first_name, last_name\n```\n\n使用 `RLIKE` 时,可使用正则表达式来匹配字符串:\n\n```\nFROM employees\n| WHERE first_name RLIKE \".leja.*\"\n| KEEP first_name, last_name\n```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.substring": "SUBSTRING",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.substring.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SUBSTRING\n 返回字符串的子字符串,用起始位置和可选长度指定\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_sub = SUBSTRING(last_name, 1, 3)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tan": "TAN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tan.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TAN\n 返回角度的正切三角函数。\n\n ```\n ROW a=1.8 \n | EVAL tan=TAN(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tanh": "TANH",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tanh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TANH\n 返回角度的双曲正切函数。\n\n ```\n ROW a=1.8 \n | EVAL tanh=TANH(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tau": "TAU",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tau.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TAU\n 返回圆的圆周长与其半径的比率。\n\n ```\n ROW TAU()\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_base64": "TO_BASE64",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_base64.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_BASE64\n 将字符串编码为 base64 字符串。\n\n ```\n row a = \"elastic\" \n | eval e = to_base64(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_boolean": "TO_BOOLEAN",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_boolean.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_BOOLEAN\n 将输入值转换为布尔值。\n 字符串值 *true* 将不区分大小写并被转换为布尔值 *true*。\n 对于任何其他值,包括空字符串,此函数将返回 *false*。\n 数字值 *0* 将转换为 *false*,任何其他值将转换为 *true*。\n\n ```\n ROW str = [\"true\", \"TRuE\", \"false\", \"\", \"yes\", \"1\"]\n | EVAL bool = TO_BOOLEAN(str)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_cartesianpoint": "TO_CARTESIANPOINT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_cartesianpoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_CARTESIANPOINT\n 将输入值转换为 `cartesian_point` 值。\n 字符串只有符合 WKT 点格式时,才能成功转换。\n\n ```\n ROW wkt = [\"POINT(4297.11 -1475.53)\", \"POINT(7580.93 2272.77)\"]\n | MV_EXPAND wkt\n | EVAL pt = TO_CARTESIANPOINT(wkt)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_cartesianshape": "TO_CARTESIANSHAPE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_cartesianshape.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_CARTESIANSHAPE\n 将输入值转换为 `cartesian_shape` 值。\n 字符串只有符合 WKT 格式时,才能成功转换。\n\n ```\n ROW wkt = [\"POINT(4297.11 -1475.53)\", \"POLYGON ((3339584.72 1118889.97, 4452779.63 4865942.27, 2226389.81 4865942.27, 1113194.90 2273030.92, 3339584.72 1118889.97))\"]\n | MV_EXPAND wkt\n | EVAL geom = TO_CARTESIANSHAPE(wkt)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_datetime": "TO_DATETIME",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_datetime.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DATETIME\n 将输入值转换为日期值。\n 仅当字符串采用 `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` 格式时,才可进行成功转换。\n 要转换其他格式的日期,请使用 `DATE_PARSE`。\n\n ```\n ROW string = [\"1953-09-02T00:00:00.000Z\", \"1964-06-02T00:00:00.000Z\", \"1964-06-02 00:00:00\"]\n | EVAL datetime = TO_DATETIME(string)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_degrees": "TO_DEGREES",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_degrees.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DEGREES\n 将弧度转换为度数。\n\n ```\n ROW rad = [1.57, 3.14, 4.71]\n | EVAL deg = TO_DEGREES(rad)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_double": "TO_DOUBLE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_double.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DOUBLE\n 将输入值转换为双精度值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,\n 并转换为双精度值。布尔值 *true* 将转换为双精度值 *1.0**false* 转换为 *0.0*。\n\n ```\n ROW str1 = \"5.20128E11\", str2 = \"foo\"\n | EVAL dbl = TO_DOUBLE(\"520128000000\"), dbl1 = TO_DOUBLE(str1), dbl2 = TO_DOUBLE(str2)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_geopoint": "TO_GEOPOINT",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_geopoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_GEOPOINT\n 将输入值转换为 `geo_point` 值。\n 字符串只有符合 WKT 点格式时,才能成功转换。\n\n ```\n ROW wkt = \"POINT(42.97109630194 14.7552534413725)\"\n | EVAL pt = TO_GEOPOINT(wkt)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_geoshape": "TO_GEOSHAPE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_geoshape.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_GEOSHAPE\n 将输入值转换为 `geo_shape` 值。\n 字符串只有符合 WKT 格式时,才能成功转换。\n\n ```\n ROW wkt = \"POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))\"\n | EVAL geom = TO_GEOSHAPE(wkt)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_integer": "TO_INTEGER",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_integer.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_INTEGER\n 将输入值转换为整数值。\n 如果输入参数为日期类型,会将其值解析为自 Unix epoch 以来\n 的毫秒数,并转换为整数。\n 布尔值 *true* 将转换为整数 *1**false* 转换为 *0*。\n\n ```\n ROW long = [5013792, 2147483647, 501379200000]\n | EVAL int = TO_INTEGER(long)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_ip": "TO_IP",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_ip.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_IP\n 将输入字符串转换为 IP 值。\n\n ```\n ROW str1 = \"1.1.1.1\", str2 = \"foo\"\n | EVAL ip1 = TO_IP(str1), ip2 = TO_IP(str2)\n | WHERE CIDR_MATCH(ip1, \"1.0.0.0/8\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_long": "TO_LONG",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_long.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_LONG\n 将输入值转换为长整型值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,并转换为长整型值。\n 布尔值 *true* 将转换为长整型值 *1**false* 转换为 *0*。\n\n ```\n ROW str1 = \"2147483648\", str2 = \"2147483648.2\", str3 = \"foo\"\n | EVAL long1 = TO_LONG(str1), long2 = TO_LONG(str2), long3 = TO_LONG(str3)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_lower": "TO_LOWER",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_lower.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_LOWER\n 返回一个新字符串,表示已将输入字符串转为小写。\n\n ```\n ROW message = \"Some Text\"\n | EVAL message_lower = TO_LOWER(message)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_radians": "TO_RADIANS",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_radians.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_RADIANS\n 将度数转换为弧度。\n\n ```\n ROW deg = [90.0, 180.0, 270.0]\n | EVAL rad = TO_RADIANS(deg)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_string": "TO_STRING",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_string.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_STRING\n 将输入值转换为字符串。\n\n ```\n ROW a=10\n | EVAL j = TO_STRING(a)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_unsigned_long": "TO_UNSIGNED_LONG",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_unsigned_long.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_UNSIGNED_LONG\n 将输入值转换为无符号长整型值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,并转换为无符号长整型值。\n 布尔值 *true* 将转换为无符号长整型值 *1**false* 转换为 *0*。\n\n ```\n ROW str1 = \"2147483648\", str2 = \"2147483648.2\", str3 = \"foo\"\n | EVAL long1 = TO_UNSIGNED_LONG(str1), long2 = TO_ULONG(str2), long3 = TO_UL(str3)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_upper": "TO_UPPER",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_upper.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_UPPER\n 返回一个新字符串,表示已将输入字符串转为大写。\n\n ```\n ROW message = \"Some Text\"\n | EVAL message_upper = TO_UPPER(message)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_version": "TO_VERSION",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.to_version.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_VERSION\n 将输入字符串转换为版本值。\n\n ```\n ROW v = TO_VERSION(\"1.2.3\")\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.trim": "TRIM",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.trim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TRIM\n 从字符串中移除前导和尾随空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = TRIM(message)\n | EVAL color = TRIM(color)\n ```\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.where": "WHERE",
"textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.where.markdown": "### WHERE\n使用 `WHERE` 可生成一个表,其中包含输入表中所提供的条件评估为 `true` 的所有行:\n \n```\nFROM employees\n| KEEP first_name, last_name, still_hired\n| WHERE still_hired == true\n```\n\n#### 运算符\n\n请参阅**运算符**了解所支持的运算符的概览。\n\n#### 函数\n`WHERE` 支持各种用于计算值的函数。请参阅**函数**了解更多信息。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.documentationLabel": "文档",
"languageDocumentationPopover.documentationESQL.abs": "ABS",
"languageDocumentationPopover.documentationESQL.abs.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ABS\n 返回绝对值。\n\n ```\n ROW number = -1.0 \n | EVAL abs_number = ABS(number)\n ```\n ",
"languageDocumentationPopover.documentationESQL.acos": "ACOS",
"languageDocumentationPopover.documentationESQL.acos.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ACOS\n 返回 `n` 的反余弦作为角度,以弧度表示。\n\n ```\n ROW a=.9\n | EVAL acos=ACOS(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.asin": "ASIN",
"languageDocumentationPopover.documentationESQL.asin.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ASIN\n 返回输入数字表达式的反正弦\n 作为角度,以弧度表示。\n\n ```\n ROW a=.9\n | EVAL asin=ASIN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.atan": "ATAN",
"languageDocumentationPopover.documentationESQL.atan.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ATAN\n 返回输入数字表达式的反正切\n 作为角度,以弧度表示。\n\n ```\n ROW a=12.9\n | EVAL atan=ATAN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.atan2": "ATAN2",
"languageDocumentationPopover.documentationESQL.atan2.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ATAN2\n 笛卡儿平面中正 x 轴\n 与从原点到点 (x , y) 构成的射线之间的角度,以弧度表示。\n\n ```\n ROW y=12.9, x=.6\n | EVAL atan2=ATAN2(y, x)\n ```\n ",
"languageDocumentationPopover.documentationESQL.autoBucketFunction": "BUCKET",
"languageDocumentationPopover.documentationESQL.autoBucketFunction.markdown": "### BUCKET\n用日期时间或数字输入创建值存储桶的分组。存储桶的大小可以直接提供或基于建议的计数和值范围进行选择。\n\n`BUCKET` 以两种模式运行:\n\n1.在此模式下基于存储桶计数建议(四个参数)和范围计算存储桶的大小。\n2.在此模式下直接提供存储桶大小(两个参数)。\n\n使用存储桶的目标数量、起始范围和结束范围`BUCKET` 将选取适当的存储桶大小以生成目标数量或更小数量的存储桶。\n\n例如一年请求多达 20 个存储桶会按每月时间间隔组织数据:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hire_date = MV_SORT(VALUES(hire_date)) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT hire_date\n```\n\n**注意**:目标并不是提供存储桶的确切目标数量,而是选择一个范围,最多提供存储桶的目标数量。\n\n可以组合 `BUCKET` 与聚合以创建直方图:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_month = COUNT(*) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT month\n```\n\n**注意**`BUCKET` 不会创建未匹配任何文档的存储桶。因此,上一示例缺少 `1985-03-01` 和其他日期。\n\n如果需要更多存储桶可能导致更小的范围。例如如果一年内最多请求 100 个存储桶,会导致周期为周的存储桶:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 100, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT week\n```\n\n**注意**`AUTO_BUCKET` 不筛选任何行。它只会使用提供的范围来选取适当的存储桶大小。对于值超出范围的行,它会返回与超出范围的存储桶对应的存储桶值。组合 `BUCKET` 与 `WHERE` 可筛选行。\n\n如果提前已知所需存储桶大小则只需提供它作为第二个参数而忽略范围\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS hires_per_week = COUNT(*) BY week = BUCKET(hire_date, 1 week)\n| SORT week\n```\n\n**注意**:提供存储桶大小作为第二个参数时,它必须为持续时间或日期期间。\n\n`BUCKET` 还可对数字字段执行操作。例如,要创建工资直方图:\n\n```\nFROM employees\n| STATS COUNT(*) by bs = BUCKET(salary, 20, 25324, 74999)\n| SORT bs\n```\n\n与前面的有意筛选日期范围示例不同您极少想要筛选数值范围。您必须分别查找最小值和最大值。ES|QL 尚未提供简便方法来自动执行此操作。\n\n如果提前已知所需存储桶大小则可以忽略该范围。只需提供它作为第二个参数即可\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS c = COUNT(1) BY b = BUCKET(salary, 5000.)\n| SORT b\n```\n\n**注意**:提供存储桶大小作为第二个参数时,它必须为 **浮点类型**。\n\n这里提供了一个示例用于为过去 24 小时创建小时存储桶,并计算每小时的事件数:\n\n```\nFROM sample_data\n| WHERE @timestamp >= NOW() - 1 day and @timestamp < NOW()\n| STATS COUNT(*) BY bucket = BUCKET(@timestamp, 25, NOW() - 1 day, NOW())\n```\n\n这里提供了一个示例用于为 1985 年创建月度存储桶,并按聘用月份计算平均工资:\n\n```\nFROM employees\n| WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n| STATS AVG(salary) BY bucket = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n| SORT bucket\n```\n\n`BUCKET` 可用在 `STATS …​ BY …` 命令的聚合和分组部分, 前提是在聚合部分中,该函数 **由在分组部分中定义的别名引用**,或使用完全相同的表达式调用。\n\n例如\n\n```\nFROM employees\n| STATS s1 = b1 + 1, s2 = BUCKET(salary / 1000 + 999, 50.) + 2 BY b1 = BUCKET(salary / 100 + 99, 50.), b2 = BUCKET(salary / 1000 + 999, 50.)\n| SORT b1, b2\n| KEEP s1, b1, s2, b2\n```\n ",
"languageDocumentationPopover.documentationESQL.binaryOperators": "二进制运算符",
"languageDocumentationPopover.documentationESQL.binaryOperators.markdown": "### 二进制运算符\n支持这些二进制比较运算符\n\n* 等于:`==`\n* 不等于:`!=`\n* 小于:`<`\n* 小于或等于:`<=`\n* 大于:`>`\n* 大于或等于:`>=`\n* 加:`+`\n* 减:`-`\n* 乘:`*`\n* 除:`/`\n* 取模:`%`\n ",
"languageDocumentationPopover.documentationESQL.booleanOperators": "布尔运算符",
"languageDocumentationPopover.documentationESQL.booleanOperators.markdown": "### 布尔运算符\n支持以下布尔运算符\n\n* `AND`\n* `OR`\n* `NOT`\n ",
"languageDocumentationPopover.documentationESQL.bucket": "BUCKET",
"languageDocumentationPopover.documentationESQL.bucket.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### BUCKET\n 用日期时间或数字输入创建值(存储桶)的分组。\n 存储桶的大小可以直接提供,或基于建议的计数和值范围进行选择。\n\n ```\n FROM employees\n | WHERE hire_date >= \"1985-01-01T00:00:00Z\" AND hire_date < \"1986-01-01T00:00:00Z\"\n | STATS hire_date = MV_SORT(VALUES(hire_date)) BY month = BUCKET(hire_date, 20, \"1985-01-01T00:00:00Z\", \"1986-01-01T00:00:00Z\")\n | SORT hire_date\n ```\n ",
"languageDocumentationPopover.documentationESQL.case": "CASE",
"languageDocumentationPopover.documentationESQL.case.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CASE\n 接受成对的条件和值。此函数返回属于第一个\n 评估为 `true` 的条件的值。\n\n 如果参数数量为奇数,则最后一个参数为\n 在无条件匹配时返回的默认值。如果参数数量为偶数,且\n 无任何条件匹配,则此函数返回 `null`。\n\n ```\n FROM employees\n | EVAL type = CASE(\n languages <= 1, \"monolingual\",\n languages <= 2, \"bilingual\",\n \"polyglot\")\n | KEEP emp_no, languages, type\n ```\n ",
"languageDocumentationPopover.documentationESQL.castOperator": "Cast (::)",
"languageDocumentationPopover.documentationESQL.castOperator.markdown": "### CAST (`::`)\n`::` 运算符为 `TO_<type>` 类型转换函数提供了实用的替代语法。\n\n例如\n```\nROW ver = CONCAT((\"0\"::INT + 1)::STRING, \".2.3\")::VERSION\n```\n ",
"languageDocumentationPopover.documentationESQL.cbrt": "CBRT",
"languageDocumentationPopover.documentationESQL.cbrt.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CBRT\n 返回数字的立方根。输入可以为任何数字值,返回值始终为双精度值。\n 无穷大的立方根为 null。\n\n ```\n ROW d = 1000.0\n | EVAL c = cbrt(d)\n ```\n ",
"languageDocumentationPopover.documentationESQL.ceil": "CEIL",
"languageDocumentationPopover.documentationESQL.ceil.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CEIL\n 将数字四舍五入为最近的整数。\n\n ```\n ROW a=1.8\n | EVAL a=CEIL(a)\n ```\n 注意:对于 `long`(包括无符号值)和 `integer`,这相当于“无操作”。对于 `double`,这会提取最接近整数的 `double` 值,类似于 Math.ceil。\n ",
"languageDocumentationPopover.documentationESQL.cidr_match": "CIDR_MATCH",
"languageDocumentationPopover.documentationESQL.cidr_match.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CIDR_MATCH\n 如果提供的 IP 包含在所提供的其中一个 CIDR 块中,则返回 true。\n\n ```\n FROM hosts \n | WHERE CIDR_MATCH(ip1, \"127.0.0.2/32\", \"127.0.0.3/32\") \n | KEEP card, host, ip0, ip1\n ```\n ",
"languageDocumentationPopover.documentationESQL.coalesce": "COALESCE",
"languageDocumentationPopover.documentationESQL.coalesce.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COALESCE\n 返回它的第一个不为 null 的参数。如果所有参数均为 null则返回 `null`。\n\n ```\n ROW a=null, b=\"b\"\n | EVAL COALESCE(a, b)\n ```\n ",
"languageDocumentationPopover.documentationESQL.concat": "CONCAT",
"languageDocumentationPopover.documentationESQL.concat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### CONCAT\n 串联两个或多个字符串。\n\n ```\n FROM employees\n | KEEP first_name, last_name\n | EVAL fullname = CONCAT(first_name, \" \", last_name)\n ```\n ",
"languageDocumentationPopover.documentationESQL.cos": "COS",
"languageDocumentationPopover.documentationESQL.cos.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COS\n 返回角度的余弦。\n\n ```\n ROW a=1.8 \n | EVAL cos=COS(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.cosh": "COSH",
"languageDocumentationPopover.documentationESQL.cosh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### COSH\n 返回角度的双曲余弦。\n\n ```\n ROW a=1.8 \n | EVAL cosh=COSH(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.date_diff": "DATE_DIFF",
"languageDocumentationPopover.documentationESQL.date_diff.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_DIFF\n 从 `endTimestamp` 中减去 `startTimestamp`,并以倍数 `unit` 返回差异。\n 如果 `startTimestamp` 晚于 `endTimestamp`,则返回负值。\n\n ```\n ROW date1 = TO_DATETIME(\"2023-12-02T11:00:00.000Z\"), date2 = TO_DATETIME(\"2023-12-02T11:00:00.001Z\")\n | EVAL dd_ms = DATE_DIFF(\"microseconds\", date1, date2)\n ```\n ",
"languageDocumentationPopover.documentationESQL.date_extract": "DATE_EXTRACT",
"languageDocumentationPopover.documentationESQL.date_extract.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_EXTRACT\n 提取日期的某些部分,如年、月、日、小时。\n\n ```\n ROW date = DATE_PARSE(\"yyyy-MM-dd\", \"2022-05-06\")\n | EVAL year = DATE_EXTRACT(\"year\", date)\n ```\n ",
"languageDocumentationPopover.documentationESQL.date_format": "DATE_FORMAT",
"languageDocumentationPopover.documentationESQL.date_format.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_FORMAT\n 以提供的格式返回日期的字符串表示形式。\n\n ```\n FROM employees\n | KEEP first_name, last_name, hire_date\n | EVAL hired = DATE_FORMAT(\"YYYY-MM-dd\", hire_date)\n ```\n ",
"languageDocumentationPopover.documentationESQL.date_parse": "DATE_PARSE",
"languageDocumentationPopover.documentationESQL.date_parse.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_PARSE\n 通过使用在第一个参数中指定的格式来解析第二个参数,从而返回日期。\n\n ```\n ROW date_string = \"2022-05-06\"\n | EVAL date = DATE_PARSE(\"yyyy-MM-dd\", date_string)\n ```\n ",
"languageDocumentationPopover.documentationESQL.date_trunc": "DATE_TRUNC",
"languageDocumentationPopover.documentationESQL.date_trunc.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### DATE_TRUNC\n 将日期向下舍入到最近的时间间隔。\n\n ```\n FROM employees\n | KEEP first_name, last_name, hire_date\n | EVAL year_hired = DATE_TRUNC(1 year, hire_date)\n ```\n ",
"languageDocumentationPopover.documentationESQL.dissect": "DISSECT",
"languageDocumentationPopover.documentationESQL.dissect.markdown": "### DISSECT\n使用 `DISSECT`,您可以从字符串中提取结构化数据。`DISSECT` 将根据基于分隔符的模式来匹配字符串,并提取指定键作为列。\n\n请参阅[分解处理器文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/dissect-processor.html)了解分解模式的语法。\n\n```\nROW a = \"1953-01-23T12:15:00Z - some text - 127.0.0.1\"\n| DISSECT a \"%'{Y}-%{M}-%{D}T%{h}:%{m}:%{s}Z - %{msg} - %{ip}'\"\n``` ",
"languageDocumentationPopover.documentationESQL.drop": "DROP",
"languageDocumentationPopover.documentationESQL.drop.markdown": "### DROP\n使用 `DROP` 可从表中移除列:\n \n```\nFROM employees\n| DROP height\n```\n\n您不必按名称指定每个列而可以使用通配符丢弃名称匹配某种模式的所有列\n\n```\nFROM employees\n| DROP height*\n```\n ",
"languageDocumentationPopover.documentationESQL.e": "E",
"languageDocumentationPopover.documentationESQL.e.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### E\n 返回 Euler 函数的编号。\n\n ```\n ROW E()\n ```\n ",
"languageDocumentationPopover.documentationESQL.ends_with": "ENDS_WITH",
"languageDocumentationPopover.documentationESQL.ends_with.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ENDS_WITH\n 返回布尔值,指示关键字字符串是否以另一个字符串结尾。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_E = ENDS_WITH(last_name, \"d\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.enrich": "ENRICH",
"languageDocumentationPopover.documentationESQL.enrich.markdown": "### ENRICH\n您可以使用 `ENRICH` 将来自现有索引的数据添加到传入记录中。它类似于[采集扩充](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html),但作用于查询时间。\n\n```\nROW language_code = \"1\"\n| ENRICH languages_policy\n```\n\n执行 `ENRICH` 需要[扩充策略](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html#enrich-policy)。扩充策略定义一个匹配字段(键字段)和一组扩充字段。\n\n`ENRICH` 将根据匹配字段值在[扩充索引](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html#enrich-index)中查找记录。输入数据集中的匹配键可以使用 `ON <field-name>` 来定义;如果未指定,将对字段名称与在扩充策略中定义的匹配字段相同的字段执行匹配。\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a\n```\n\n您可以使用 `WITH <field1>, <field2>...` 语法指定必须将哪些属性(在那些在策略中定义为扩充字段的字段之间)添加到结果中。\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a WITH language_name\n```\n\n还可以使用 `WITH new_name=<field1>` 重命名属性\n\n```\nROW a = \"1\"\n| ENRICH languages_policy ON a WITH name = language_name\n```\n\n默认情况下如果未定义任何 `WITH``ENRICH` 会将在扩充策略中定义的所有扩充字段添加到结果中。\n\n如果出现名称冲突新创建的字段将覆盖现有字段。\n ",
"languageDocumentationPopover.documentationESQL.eval": "EVAL",
"languageDocumentationPopover.documentationESQL.eval.markdown": "### EVAL\n`EVAL` 允许您添加新列:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| EVAL height_feet = height * 3.281, height_cm = height * 100\n```\n\n如果指定列已存在将丢弃现有列并将新列追加到表后面\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| EVAL height = height * 3.281\n```\n\n#### 函数\n`EVAL` 支持各种用于计算值的函数。请参阅“函数”了解更多信息。\n ",
"languageDocumentationPopover.documentationESQL.floor": "FLOOR",
"languageDocumentationPopover.documentationESQL.floor.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### FLOOR\n 将数字向下舍入到最近的整数。\n\n ```\n ROW a=1.8\n | EVAL a=FLOOR(a)\n ```\n 注意:对于 `long`(包括无符号值)和 `integer`,这相当于“无操作”。\n 对于 `double`,这会提取最接近整数的 `double` 值,\n 类似于 Math.floor。\n ",
"languageDocumentationPopover.documentationESQL.from": "FROM",
"languageDocumentationPopover.documentationESQL.from_base64": "FROM_BASE64",
"languageDocumentationPopover.documentationESQL.from_base64.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### FROM_BASE64\n 解码 base64 字符串。\n\n ```\n row a = \"ZWxhc3RpYw==\" \n | eval d = from_base64(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.from.markdown": "### FROM\n`FROM` 源命令返回一个表,其中最多包含 10,000 个来自数据流、索引或别名的文档。生成的表中的每一行代表一个文档。每一列对应一个字段,并可以通过该字段的名称进行访问。\n\n```\nFROM employees\n```\n\n您可以使用[日期数学表达式](https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#api-date-math-index-names)来引用索引、别名和数据流。这可能对时间序列数据非常有用。\n\n使用逗号分隔列表或通配符可查询多个数据流、索引或别名\n\n```\nFROM employees-00001,employees-*\n```\n\n#### 元数据\n\nES|QL 可访问以下元数据字段:\n\n* `_index`:文档所属的索引。字段类型为 `keyword`.\n* `_id`:源文档的 ID。字段类型为 `keyword`.\n* `_version`:源文档的版本。字段类型为 `long`。\n\n使用 `METADATA` 指令可启用元数据字段:\n\n```\nFROM index [METADATA _index, _id]\n```\n\n元数据字段仅在数据源为索引时可用。因此`FROM` 是唯一支持 `METADATA` 指令的源命令。\n\n启用后这些字段将可用于后续处理命令就像其他索引字段一样\n\n```\nFROM ul_logs, apps [METADATA _index, _version]\n| WHERE id IN (13, 14) AND _version == 1\n| EVAL key = CONCAT(_index, \"_\", TO_STR(id))\n| SORT id, _index\n| KEEP id, _index, _version, key\n```\n\n此外与索引字段类似一旦执行了聚合后续命令将无法再访问元数据字段除非它用作分组字段\n\n```\nFROM employees [METADATA _index, _id]\n| STATS max = MAX(emp_no) BY _index\n```\n ",
"languageDocumentationPopover.documentationESQL.greatest": "GREATEST",
"languageDocumentationPopover.documentationESQL.greatest.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### GREATEST\n 返回多个列中的最大值。除了可一次对多个列运行以外,\n 此函数与 `MV_MAX` 类似。\n\n ```\n ROW a = 10, b = 20\n | EVAL g = GREATEST(a, b)\n ```\n 注意:对 `keyword` 或 `text` 字段运行时,此函数将按字母顺序返回最后一个字符串。对 `boolean` 列运行时,如果任何值为 `true`,此函数将返回 `true`。\n ",
"languageDocumentationPopover.documentationESQL.grok": "GROK",
"languageDocumentationPopover.documentationESQL.grok.markdown": "### GROK\n使用 `GROK`,您可以从字符串中提取结构化数据。`GROK` 将基于正则表达式根据模式来匹配字符串,并提取指定模式作为列。\n\n请参阅 [grok 处理器文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/grok-processor.html)了解 grok 模式的语法。\n\n```\nROW a = \"12 15.5 15.6 true\"\n| GROK a \"%'{NUMBER:b:int}' %'{NUMBER:c:float}' %'{NUMBER:d:double}' %'{WORD:e:boolean}'\"\n```\n ",
"languageDocumentationPopover.documentationESQL.inOperator": "IN",
"languageDocumentationPopover.documentationESQL.inOperator.markdown": "### IN\n`IN` 运算符允许测试字段或表达式是否等于文本、字段或表达式列表中的元素:\n\n```\nROW a = 1, b = 4, c = 3\n| WHERE c-a IN (3, b / 2, a)\n```\n ",
"languageDocumentationPopover.documentationESQL.ip_prefix": "IP_PREFIX",
"languageDocumentationPopover.documentationESQL.ip_prefix.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### IP_PREFIX\n 截短 IP 至给定的前缀长度。\n\n ```\n row ip4 = to_ip(\"1.2.3.4\"), ip6 = to_ip(\"fe80::cae2:65ff:fece:feb9\")\n | eval ip4_prefix = ip_prefix(ip4, 24, 0), ip6_prefix = ip_prefix(ip6, 0, 112);\n ```\n ",
"languageDocumentationPopover.documentationESQL.keep": "KEEP",
"languageDocumentationPopover.documentationESQL.keep.markdown": "### KEEP\n使用 `KEEP` 命令,您可以指定将返回哪些列以及返回这些列的顺序。\n\n要限制返回的列数请使用列名的逗号分隔列表。将按指定顺序返回这些列\n \n```\nFROM employees\n| KEEP first_name, last_name, height\n```\n\n您不必按名称指定每个列而可以使用通配符返回名称匹配某种模式的所有列\n\n```\nFROM employees\n| KEEP h*\n```\n\n星号通配符 (`*`) 自身将转换为不与其他参数匹配的所有列。此查询将首先返回所有名称以 h 开头的所有列,随后返回所有其他列:\n\n```\nFROM employees\n| KEEP h*, *\n```\n ",
"languageDocumentationPopover.documentationESQL.least": "LEAST",
"languageDocumentationPopover.documentationESQL.least.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LEAST\n 返回多个列中的最小值。除了可一次对多个列运行以外,此函数与 `MV_MIN` 类似。\n\n ```\n ROW a = 10, b = 20\n | EVAL l = LEAST(a, b)\n ```\n ",
"languageDocumentationPopover.documentationESQL.left": "LEFT",
"languageDocumentationPopover.documentationESQL.left.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LEFT\n 返回从“字符串”中提取“长度”字符的子字符串,从左侧开始。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL left = LEFT(last_name, 3)\n | SORT last_name ASC\n | LIMIT 5\n ```\n ",
"languageDocumentationPopover.documentationESQL.length": "LENGTH",
"languageDocumentationPopover.documentationESQL.length.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LENGTH\n 返回字符串的字符长度。\n\n ```\n FROM employees\n | KEEP first_name, last_name\n | EVAL fn_length = LENGTH(first_name)\n ```\n ",
"languageDocumentationPopover.documentationESQL.limit": "LIMIT",
"languageDocumentationPopover.documentationESQL.limit.markdown": "### LIMIT\n`LIMIT` 处理命令允许您限制行数:\n \n```\nFROM employees\n| LIMIT 5\n```\n ",
"languageDocumentationPopover.documentationESQL.locate": "LOCATE",
"languageDocumentationPopover.documentationESQL.locate.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOCATE\n 返回一个整数,指示关键字子字符串在另一字符串中的位置\n\n ```\n row a = \"hello\"\n | eval a_ll = locate(a, \"ll\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.log": "LOG",
"languageDocumentationPopover.documentationESQL.log.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOG\n 以某底数返回值的对数。输入可以为任何数字值,返回值始终为双精度值。\n\n 求零、负数的对数,以及底数为一时将返回 `null`,并显示警告。\n\n ```\n ROW base = 2.0, value = 8.0\n | EVAL s = LOG(base, value)\n ```\n ",
"languageDocumentationPopover.documentationESQL.log10": "LOG10",
"languageDocumentationPopover.documentationESQL.log10.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LOG10\n 以底数 10 返回值的对数。输入可以为任何数字值,返回值始终为双精度值。\n\n 求 0 和负数的对数时将返回 `null`,并显示警告。\n\n ```\n ROW d = 1000.0 \n | EVAL s = LOG10(d)\n ```\n ",
"languageDocumentationPopover.documentationESQL.ltrim": "LTRIM",
"languageDocumentationPopover.documentationESQL.ltrim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### LTRIM\n 从字符串中移除前导空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = LTRIM(message)\n | EVAL color = LTRIM(color)\n | EVAL message = CONCAT(\"'\", message, \"'\")\n | EVAL color = CONCAT(\"'\", color, \"'\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.markdown": "## ES|QL\n\nES|QLElasticsearch 查询语言)查询包含一系列命令,它们用管道字符分隔:`|`。每个查询以**源命令**开头,它会生成一个表,其中通常包含来自 Elasticsearch 的数据。\n\n源命令可后接一个或多个**处理命令**。处理命令可通过添加、移除以及更改行和列来更改前一个命令的输出表。\n\n```\nsource-command\n| processing-command1\n| processing-command2\n```\n\n查询的结果为由最后的处理命令生成的表。 \n ",
"languageDocumentationPopover.documentationESQL.mv_append": "MV_APPEND",
"languageDocumentationPopover.documentationESQL.mv_append.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_APPEND\n 串联两个多值字段的值。\n\n ",
"languageDocumentationPopover.documentationESQL.mv_avg": "MV_AVG",
"languageDocumentationPopover.documentationESQL.mv_avg.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_AVG\n 将多值字段转换为包含所有值的平均值的单值字段。\n\n ```\n ROW a=[3, 5, 1, 6]\n | EVAL avg_a = MV_AVG(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_concat": "MV_CONCAT",
"languageDocumentationPopover.documentationESQL.mv_concat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_CONCAT\n 将多值字符串表达式转换为单值列,其中包含由分隔符分隔的所有值的串联形式。\n\n ```\n ROW a=[\"foo\", \"zoo\", \"bar\"]\n | EVAL j = MV_CONCAT(a, \", \")\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_count": "MV_COUNT",
"languageDocumentationPopover.documentationESQL.mv_count.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_COUNT\n 将多值表达式转换为包含值计数的单值列。\n\n ```\n ROW a=[\"foo\", \"zoo\", \"bar\"]\n | EVAL count_a = MV_COUNT(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_dedupe": "MV_DEDUPE",
"languageDocumentationPopover.documentationESQL.mv_dedupe.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_DEDUPE\n 移除多值字段中的重复值。\n\n ```\n ROW a=[\"foo\", \"foo\", \"bar\", \"foo\"]\n | EVAL dedupe_a = MV_DEDUPE(a)\n ```\n 注意:`MV_DEDUPE` 可能但不会始终对列中的值进行排序。\n ",
"languageDocumentationPopover.documentationESQL.mv_first": "MV_FIRST",
"languageDocumentationPopover.documentationESQL.mv_first.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_FIRST\n 将多值表达式转换为包含第一个值的\n 单值列。这在从按已知顺序发出多值列的\n 函数(如 `SPLIT`)中读取数据时尤其有用。\n\n 无法保证从底层存储\n 读取多值字段的顺序。它 *通常* 为升序,但不应\n 依赖于此。如果需要最小值,请使用 `MV_MIN` 而不是\n `MV_FIRST`。`MV_MIN` 针对排序值进行了优化,因此\n 对 `MV_FIRST` 没有性能优势。\n\n ```\n ROW a=\"foo;bar;baz\"\n | EVAL first_a = MV_FIRST(SPLIT(a, \";\"))\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_last": "MV_LAST",
"languageDocumentationPopover.documentationESQL.mv_last.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_LAST\n 将多值表达式转换为包含最后一个值的单值\n 列。这在从按已知顺序发出多值列的函数\n (如 `SPLIT`)中读取数据时尤其有用。\n\n 无法保证从底层存储\n 读取多值字段的顺序。它 *通常* 为升序,但不应\n 依赖于此。如果需要最大值,请使用 `MV_MAX` 而不是\n `MV_LAST`。`MV_MAX` 针对排序值进行了优化,因此\n 对 `MV_LAST` 没有性能优势。\n\n ```\n ROW a=\"foo;bar;baz\"\n | EVAL last_a = MV_LAST(SPLIT(a, \";\"))\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_max": "MV_MAX",
"languageDocumentationPopover.documentationESQL.mv_max.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MAX\n 将多值表达式转换为包含最大值的单值列。\n\n ```\n ROW a=[3, 5, 1]\n | EVAL max_a = MV_MAX(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_median": "MV_MEDIAN",
"languageDocumentationPopover.documentationESQL.mv_median.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MEDIAN\n 将多值字段转换为包含中位数值的单值字段。\n\n ```\n ROW a=[3, 5, 1]\n | EVAL median_a = MV_MEDIAN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_min": "MV_MIN",
"languageDocumentationPopover.documentationESQL.mv_min.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_MIN\n 将多值表达式转换为包含最小值的单值列。\n\n ```\n ROW a=[2, 1]\n | EVAL min_a = MV_MIN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_slice": "MV_SLICE",
"languageDocumentationPopover.documentationESQL.mv_slice.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SLICE\n 使用起始和结束索引值返回多值字段的子集。\n\n ```\n row a = [1, 2, 2, 3]\n | eval a1 = mv_slice(a, 1), a2 = mv_slice(a, 2, 3)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_sort": "MV_SORT",
"languageDocumentationPopover.documentationESQL.mv_sort.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SORT\n 按字典顺序对多值字段排序。\n\n ```\n ROW a = [4, 2, -3, 2]\n | EVAL sa = mv_sort(a), sd = mv_sort(a, \"DESC\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_sum": "MV_SUM",
"languageDocumentationPopover.documentationESQL.mv_sum.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_SUM\n 将多值字段转换为包含所有值的总和的单值字段。\n\n ```\n ROW a=[3, 5, 6]\n | EVAL sum_a = MV_SUM(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.mv_zip": "MV_ZIP",
"languageDocumentationPopover.documentationESQL.mv_zip.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### MV_ZIP\n 组合两个使用分隔符联接在一起的多值字段中的值。\n\n ```\n ROW a = [\"x\", \"y\", \"z\"], b = [\"1\", \"2\"]\n | EVAL c = mv_zip(a, b, \"-\")\n | KEEP a, b, c\n ```\n ",
"languageDocumentationPopover.documentationESQL.mvExpand": "MV_EXPAND",
"languageDocumentationPopover.documentationESQL.mvExpand.markdown": "### MV_EXPAND\n`MV_EXPAND` 处理命令将多值字段扩展成每个值一行,从而复制其他字段: \n```\nROW a=[1,2,3], b=\"b\", j=[\"a\",\"b\"]\n| MV_EXPAND a\n```\n ",
"languageDocumentationPopover.documentationESQL.now": "NOW",
"languageDocumentationPopover.documentationESQL.now.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### NOW\n 返回当前日期和时间。\n\n ```\n ROW current_date = NOW()\n ```\n ",
"languageDocumentationPopover.documentationESQL.pi": "PI",
"languageDocumentationPopover.documentationESQL.pi.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### PI\n 返回 Pi即圆的周长与其直径的比率。\n\n ```\n ROW PI()\n ```\n ",
"languageDocumentationPopover.documentationESQL.pow": "POW",
"languageDocumentationPopover.documentationESQL.pow.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### POW\n 返回提升为 `exponent` 幂的 `base` 的值。\n\n ```\n ROW base = 2.0, exponent = 2\n | EVAL result = POW(base, exponent)\n ```\n 注意:此处仍可能使双精度结果溢出;在该情况下,将返回 null。\n ",
"languageDocumentationPopover.documentationESQL.predicates": "Null 值",
"languageDocumentationPopover.documentationESQL.predicates.markdown": "### NULL 值\n对于 NULL 比较,请使用 `IS NULL` 和 `IS NOT NULL` 谓词:\n\n```\nFROM employees\n| WHERE birth_date IS NULL\n| KEEP first_name, last_name\n| SORT first_name\n| LIMIT 3\n```\n\n```\nFROM employees\n| WHERE is_rehired IS NOT NULL\n| STATS count(emp_no)\n```\n ",
"languageDocumentationPopover.documentationESQL.rename": "RENAME",
"languageDocumentationPopover.documentationESQL.rename.markdown": "### RENAME\n请使用 `RENAME` 通过以下语法对列重命名:\n\n```\nRENAME <old-name> AS <new-name>\n```\n\n例如\n\n```\nFROM employees\n| KEEP first_name, last_name, still_hired\n| RENAME still_hired AS employed\n```\n\n如果使用新名称的列已存在将用新列替换该列。\n\n可以使用单个 `RENAME` 命令对多个列重命名:\n\n```\nFROM employees\n| KEEP first_name, last_name\n| RENAME first_name AS fn, last_name AS ln\n```\n ",
"languageDocumentationPopover.documentationESQL.repeat": "REPEAT",
"languageDocumentationPopover.documentationESQL.repeat.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### REPEAT\n 返回通过串联 `string` 自身与指定次数 `number` 构造而成的字符串。\n\n ```\n ROW a = \"Hello!\"\n | EVAL triple_a = REPEAT(a, 3);\n ```\n ",
"languageDocumentationPopover.documentationESQL.replace": "REPLACE",
"languageDocumentationPopover.documentationESQL.replace.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### REPLACE\n 此函数将字符串 `str` 中正则表达式 `regex` 的任何匹配项\n 替换为替代字符串 `newStr`。\n\n ```\n ROW str = \"Hello World\"\n | EVAL str = REPLACE(str, \"World\", \"Universe\")\n | KEEP str\n ```\n ",
"languageDocumentationPopover.documentationESQL.right": "RIGHT",
"languageDocumentationPopover.documentationESQL.right.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### RIGHT\n 返回从“字符串”中提取“长度”字符的子字符串,从右侧开始。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL right = RIGHT(last_name, 3)\n | SORT last_name ASC\n | LIMIT 5\n ```\n ",
"languageDocumentationPopover.documentationESQL.round": "ROUND",
"languageDocumentationPopover.documentationESQL.round.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ROUND\n 将数字舍入到指定小数位数。\n 默认值为 0即返回最近的整数。如果\n 精确度为负数,则将数字舍入到\n 小数点左侧的位数。\n\n ```\n FROM employees\n | KEEP first_name, last_name, height\n | EVAL height_ft = ROUND(height * 3.281, 1)\n ```\n ",
"languageDocumentationPopover.documentationESQL.row": "ROW",
"languageDocumentationPopover.documentationESQL.row.markdown": "### ROW\n`ROW` 源命令会生成一个行,其中包含一个或多个含有您指定的值的列。这可以用于测试。\n \n```\nROW a = 1, b = \"two\", c = null\n```\n\n请使用方括号创建多值列\n\n```\nROW a = [2, 1]\n```\n\nROW 支持使用函数:\n\n```\nROW a = ROUND(1.23, 0)\n```\n ",
"languageDocumentationPopover.documentationESQL.rtrim": "RTRIM",
"languageDocumentationPopover.documentationESQL.rtrim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### RTRIM\n 从字符串中移除尾随空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = RTRIM(message)\n | EVAL color = RTRIM(color)\n | EVAL message = CONCAT(\"'\", message, \"'\")\n | EVAL color = CONCAT(\"'\", color, \"'\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.show": "SHOW",
"languageDocumentationPopover.documentationESQL.show.markdown": "### SHOW\n`SHOW <item>` 源命令返回有关部署及其功能的信息:\n\n* 使用 `SHOW INFO` 可返回部署的版本、构建日期和哈希。\n* 使用 `SHOW FUNCTIONS` 可返回所有受支持函数的列表和每个函数的概要。\n ",
"languageDocumentationPopover.documentationESQL.signum": "SIGNUM",
"languageDocumentationPopover.documentationESQL.signum.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SIGNUM\n 返回给定数字的符号。\n 它对负数返回 `-1`,对 `0` 返回 `0`,对正数返回 `1`。\n\n ```\n ROW d = 100.0\n | EVAL s = SIGNUM(d)\n ```\n ",
"languageDocumentationPopover.documentationESQL.sin": "SIN",
"languageDocumentationPopover.documentationESQL.sin.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SIN\n 返回角度的正弦三角函数。\n\n ```\n ROW a=1.8 \n | EVAL sin=SIN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.sinh": "SINH",
"languageDocumentationPopover.documentationESQL.sinh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SINH\n 返回角度的双曲正弦。\n\n ```\n ROW a=1.8 \n | EVAL sinh=SINH(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.sort": "SORT",
"languageDocumentationPopover.documentationESQL.sort.markdown": "### SORT\n使用 `SORT` 命令可对一个或多个字段上的行排序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height\n```\n\n默认排序顺序为升序。请使用 `ASC` 或 `DESC` 设置显式排序顺序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height DESC\n```\n\n如果两个行具有相同的排序键则保留原始顺序。您可以提供其他排序表达式充当连接断路器\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT height DESC, first_name ASC\n```\n\n#### `null` 值\n默认情况下会将 `null` 值视为大于任何其他值。使用升序排序顺序时,会最后对 `null` 值排序,而使用降序排序顺序时,会首先对 `null` 值排序。您可以通过提供 `NULLS FIRST` 或 `NULLS LAST` 来更改该排序:\n\n```\nFROM employees\n| KEEP first_name, last_name, height\n| SORT first_name ASC NULLS FIRST\n```\n ",
"languageDocumentationPopover.documentationESQL.split": "SPLIT",
"languageDocumentationPopover.documentationESQL.split.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SPLIT\n 将单值字符串拆分成多个字符串。\n\n ```\n ROW words=\"foo;bar;baz;qux;quux;corge\"\n | EVAL word = SPLIT(words, \";\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.sqrt": "SQRT",
"languageDocumentationPopover.documentationESQL.sqrt.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SQRT\n 返回数字的平方根。输入可以为任何数字值,返回值始终为双精度值。\n 负数和无穷大的平方根为 null。\n\n ```\n ROW d = 100.0\n | EVAL s = SQRT(d)\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_contains": "ST_CONTAINS",
"languageDocumentationPopover.documentationESQL.st_contains.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_CONTAINS\n 返回第一个几何形状是否包含第二个几何形状。\n 这是 `ST_WITHIN` 函数的反向函数。\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_CONTAINS(city_boundary, TO_GEOSHAPE(\"POLYGON((109.35 18.3, 109.45 18.3, 109.45 18.4, 109.35 18.4, 109.35 18.3))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_disjoint": "ST_DISJOINT",
"languageDocumentationPopover.documentationESQL.st_disjoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_DISJOINT\n 返回两个几何图形或几何图形列是否不相交。\n 这是 `ST_INTERSECTS` 函数的反向函数。\n 从数学上讲ST_Disjoint(A, B) ⇔ A ⋂ B = ∅\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_DISJOINT(city_boundary, TO_GEOSHAPE(\"POLYGON((-10 -60, 120 -60, 120 60, -10 60, -10 -60))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_distance": "ST_DISTANCE",
"languageDocumentationPopover.documentationESQL.st_distance.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_DISTANCE\n 计算两点之间的距离。\n 对于笛卡尔几何形状,这是以相同单位作为原始坐标时的毕达哥拉斯距离。\n 对于地理几何形状而言,这是沿着地球大圆的圆周距离(以米为单位)。\n\n ```\n FROM airports\n | WHERE abbrev == \"CPH\"\n | EVAL distance = ST_DISTANCE(location, city_location)\n | KEEP abbrev, name, location, city_location, distance\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_intersects": "ST_INTERSECTS",
"languageDocumentationPopover.documentationESQL.st_intersects.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_INTERSECTS\n 如果两个几何形状相交,则返回 true。\n 如果它们有任何共同点,包括其内点\n (沿线的点或多边形内的点),则表示它们相交。\n 这是 `ST_DISJOINT` 函数的反向函数。\n 从数学上讲ST_Intersects(A, B) ⇔ A ⋂ B ≠ ∅\n\n ```\n FROM airports\n | WHERE ST_INTERSECTS(location, TO_GEOSHAPE(\"POLYGON((42 14, 43 14, 43 15, 42 15, 42 14))\"))\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_within": "ST_WITHIN",
"languageDocumentationPopover.documentationESQL.st_within.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_WITHIN\n 返回第一个几何形状是否在第二个几何形状内。\n 这是 `ST_CONTAINS` 函数的反向函数。\n\n ```\n FROM airport_city_boundaries\n | WHERE ST_WITHIN(city_boundary, TO_GEOSHAPE(\"POLYGON((109.1 18.15, 109.6 18.15, 109.6 18.65, 109.1 18.65, 109.1 18.15))\"))\n | KEEP abbrev, airport, region, city, city_location\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_x": "ST_X",
"languageDocumentationPopover.documentationESQL.st_x.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_X\n 从提供的点中提取 `x` 坐标。\n 如果点的类型为 `geo_point`,则这等同于提取 `longitude` 值。\n\n ```\n ROW point = TO_GEOPOINT(\"POINT(42.97109629958868 14.7552534006536)\")\n | EVAL x = ST_X(point), y = ST_Y(point)\n ```\n ",
"languageDocumentationPopover.documentationESQL.st_y": "ST_Y",
"languageDocumentationPopover.documentationESQL.st_y.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### ST_Y\n 从提供的点中提取 `y` 坐标。\n 如果点的类型为 `geo_point`,则这等同于提取 `latitude` 值。\n\n ```\n ROW point = TO_GEOPOINT(\"POINT(42.97109629958868 14.7552534006536)\")\n | EVAL x = ST_X(point), y = ST_Y(point)\n ```\n ",
"languageDocumentationPopover.documentationESQL.starts_with": "STARTS_WITH",
"languageDocumentationPopover.documentationESQL.starts_with.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### STARTS_WITH\n 返回指示关键字字符串是否以另一个字符串开头的布尔值。\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_S = STARTS_WITH(last_name, \"B\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.statsby": "STATS ...BY",
"languageDocumentationPopover.documentationESQL.statsby.markdown": "### STATS ...BY\n使用 `STATS ...BY` 可根据公共值对行分组,并计算已分组行中的一个或多个聚合值。\n\n**示例**\n\n```\nFROM employees\n| STATS count = COUNT(emp_no) BY languages\n| SORT languages\n```\n\n如果省略 `BY`,输出表实际将包含一行,其中为应用于整个数据集的聚合:\n\n```\nFROM employees\n| STATS avg_lang = AVG(languages)\n```\n\n可以计算多个值\n\n```\nFROM employees\n| STATS avg_lang = AVG(languages), max_lang = MAX(languages)\n```\n\n也可以按多个值分组仅长整型和关键字家族字段支持\n\n```\nFROM employees\n| EVAL hired = DATE_FORMAT(hire_date, \"YYYY\")\n| STATS avg_salary = AVG(salary) BY hired, languages.long\n| EVAL avg_salary = ROUND(avg_salary)\n| SORT hired, languages.long\n```\n\n请参阅**聚合函数**获取可与 `STATS ...BY` 搭配使用的函数列表。\n\n聚合函数和分组表达式均接受其他函数。这在对多值列使用 `STATS...BY` 时有用。例如,要计算平均工资变动,可以首先使用 `MV_AVG` 对每名员工的多个值求平均值,然后将结果用于 `AVG` 函数:\n\n```\nFROM employees\n| STATS avg_salary_change = AVG(MV_AVG(salary_change))\n```\n\n按表达式分组的示例为根据员工姓氏的第一个字母对其进行分组\n\n```\nFROM employees\n| STATS my_count = COUNT() BY LEFT(last_name, 1)\n| SORT `LEFT(last_name, 1)`\n```\n\n指定输出列名称为可选操作。如果未指定新列名称等于该表达式。以下查询将返回名为 `AVG(salary)` 的列:\n\n```\nFROM employees\n| STATS AVG(salary)\n```\n\n由于此名称包含特殊字符在后续命令中使用该名称时需要用反撇号 (`) 引用它:\n\n```\nFROM employees\n| STATS AVG(salary)\n| EVAL avg_salary_rounded = ROUND(`AVG(salary)`)\n```\n\n**注意**:不包含任何组的 `STATS` 比添加组更快。\n\n**注意**:当前,根据单一表达式进行分组比根据许多表达式进行分组更为优化。\n ",
"languageDocumentationPopover.documentationESQL.stringOperators": "LIKE 和 RLIKE",
"languageDocumentationPopover.documentationESQL.stringOperators.markdown": "### LIKE 和 RLIKE\n使用通配符或正则表达式比较字符串时请使用 `LIKE` 或 `RLIKE`\n\n使用 `LIKE` 时,可使用通配符来匹配字符串。支持以下通配符字符:\n\n* `*` 匹配零个或更多字符。\n* `?` 匹配一个字符。\n\n```\nFROM employees\n| WHERE first_name LIKE \"?b*\"\n| KEEP first_name, last_name\n```\n\n使用 `RLIKE` 时,可使用正则表达式来匹配字符串:\n\n```\nFROM employees\n| WHERE first_name RLIKE \".leja.*\"\n| KEEP first_name, last_name\n```\n ",
"languageDocumentationPopover.documentationESQL.substring": "SUBSTRING",
"languageDocumentationPopover.documentationESQL.substring.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### SUBSTRING\n 返回字符串的子字符串,用起始位置和可选长度指定\n\n ```\n FROM employees\n | KEEP last_name\n | EVAL ln_sub = SUBSTRING(last_name, 1, 3)\n ```\n ",
"languageDocumentationPopover.documentationESQL.tan": "TAN",
"languageDocumentationPopover.documentationESQL.tan.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TAN\n 返回角度的正切三角函数。\n\n ```\n ROW a=1.8 \n | EVAL tan=TAN(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.tanh": "TANH",
"languageDocumentationPopover.documentationESQL.tanh.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TANH\n 返回角度的双曲正切函数。\n\n ```\n ROW a=1.8 \n | EVAL tanh=TANH(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.tau": "TAU",
"languageDocumentationPopover.documentationESQL.tau.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TAU\n 返回圆的圆周长与其半径的比率。\n\n ```\n ROW TAU()\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_base64": "TO_BASE64",
"languageDocumentationPopover.documentationESQL.to_base64.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_BASE64\n 将字符串编码为 base64 字符串。\n\n ```\n row a = \"elastic\" \n | eval e = to_base64(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_boolean": "TO_BOOLEAN",
"languageDocumentationPopover.documentationESQL.to_boolean.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_BOOLEAN\n 将输入值转换为布尔值。\n 字符串值 *true* 将不区分大小写并被转换为布尔值 *true*。\n 对于任何其他值,包括空字符串,此函数将返回 *false*。\n 数字值 *0* 将转换为 *false*,任何其他值将转换为 *true*。\n\n ```\n ROW str = [\"true\", \"TRuE\", \"false\", \"\", \"yes\", \"1\"]\n | EVAL bool = TO_BOOLEAN(str)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_cartesianpoint": "TO_CARTESIANPOINT",
"languageDocumentationPopover.documentationESQL.to_cartesianpoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_CARTESIANPOINT\n 将输入值转换为 `cartesian_point` 值。\n 字符串只有符合 WKT 点格式时,才能成功转换。\n\n ```\n ROW wkt = [\"POINT(4297.11 -1475.53)\", \"POINT(7580.93 2272.77)\"]\n | MV_EXPAND wkt\n | EVAL pt = TO_CARTESIANPOINT(wkt)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_cartesianshape": "TO_CARTESIANSHAPE",
"languageDocumentationPopover.documentationESQL.to_cartesianshape.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_CARTESIANSHAPE\n 将输入值转换为 `cartesian_shape` 值。\n 字符串只有符合 WKT 格式时,才能成功转换。\n\n ```\n ROW wkt = [\"POINT(4297.11 -1475.53)\", \"POLYGON ((3339584.72 1118889.97, 4452779.63 4865942.27, 2226389.81 4865942.27, 1113194.90 2273030.92, 3339584.72 1118889.97))\"]\n | MV_EXPAND wkt\n | EVAL geom = TO_CARTESIANSHAPE(wkt)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_datetime": "TO_DATETIME",
"languageDocumentationPopover.documentationESQL.to_datetime.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DATETIME\n 将输入值转换为日期值。\n 仅当字符串采用 `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` 格式时,才可进行成功转换。\n 要转换其他格式的日期,请使用 `DATE_PARSE`。\n\n ```\n ROW string = [\"1953-09-02T00:00:00.000Z\", \"1964-06-02T00:00:00.000Z\", \"1964-06-02 00:00:00\"]\n | EVAL datetime = TO_DATETIME(string)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_degrees": "TO_DEGREES",
"languageDocumentationPopover.documentationESQL.to_degrees.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DEGREES\n 将弧度转换为度数。\n\n ```\n ROW rad = [1.57, 3.14, 4.71]\n | EVAL deg = TO_DEGREES(rad)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_double": "TO_DOUBLE",
"languageDocumentationPopover.documentationESQL.to_double.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_DOUBLE\n 将输入值转换为双精度值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,\n 并转换为双精度值。布尔值 *true* 将转换为双精度值 *1.0**false* 转换为 *0.0*。\n\n ```\n ROW str1 = \"5.20128E11\", str2 = \"foo\"\n | EVAL dbl = TO_DOUBLE(\"520128000000\"), dbl1 = TO_DOUBLE(str1), dbl2 = TO_DOUBLE(str2)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_geopoint": "TO_GEOPOINT",
"languageDocumentationPopover.documentationESQL.to_geopoint.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_GEOPOINT\n 将输入值转换为 `geo_point` 值。\n 字符串只有符合 WKT 点格式时,才能成功转换。\n\n ```\n ROW wkt = \"POINT(42.97109630194 14.7552534413725)\"\n | EVAL pt = TO_GEOPOINT(wkt)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_geoshape": "TO_GEOSHAPE",
"languageDocumentationPopover.documentationESQL.to_geoshape.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_GEOSHAPE\n 将输入值转换为 `geo_shape` 值。\n 字符串只有符合 WKT 格式时,才能成功转换。\n\n ```\n ROW wkt = \"POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))\"\n | EVAL geom = TO_GEOSHAPE(wkt)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_integer": "TO_INTEGER",
"languageDocumentationPopover.documentationESQL.to_integer.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_INTEGER\n 将输入值转换为整数值。\n 如果输入参数为日期类型,会将其值解析为自 Unix epoch 以来\n 的毫秒数,并转换为整数。\n 布尔值 *true* 将转换为整数 *1**false* 转换为 *0*。\n\n ```\n ROW long = [5013792, 2147483647, 501379200000]\n | EVAL int = TO_INTEGER(long)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_ip": "TO_IP",
"languageDocumentationPopover.documentationESQL.to_ip.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_IP\n 将输入字符串转换为 IP 值。\n\n ```\n ROW str1 = \"1.1.1.1\", str2 = \"foo\"\n | EVAL ip1 = TO_IP(str1), ip2 = TO_IP(str2)\n | WHERE CIDR_MATCH(ip1, \"1.0.0.0/8\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_long": "TO_LONG",
"languageDocumentationPopover.documentationESQL.to_long.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_LONG\n 将输入值转换为长整型值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,并转换为长整型值。\n 布尔值 *true* 将转换为长整型值 *1**false* 转换为 *0*。\n\n ```\n ROW str1 = \"2147483648\", str2 = \"2147483648.2\", str3 = \"foo\"\n | EVAL long1 = TO_LONG(str1), long2 = TO_LONG(str2), long3 = TO_LONG(str3)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_lower": "TO_LOWER",
"languageDocumentationPopover.documentationESQL.to_lower.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_LOWER\n 返回一个新字符串,表示已将输入字符串转为小写。\n\n ```\n ROW message = \"Some Text\"\n | EVAL message_lower = TO_LOWER(message)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_radians": "TO_RADIANS",
"languageDocumentationPopover.documentationESQL.to_radians.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_RADIANS\n 将度数转换为弧度。\n\n ```\n ROW deg = [90.0, 180.0, 270.0]\n | EVAL rad = TO_RADIANS(deg)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_string": "TO_STRING",
"languageDocumentationPopover.documentationESQL.to_string.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_STRING\n 将输入值转换为字符串。\n\n ```\n ROW a=10\n | EVAL j = TO_STRING(a)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_unsigned_long": "TO_UNSIGNED_LONG",
"languageDocumentationPopover.documentationESQL.to_unsigned_long.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_UNSIGNED_LONG\n 将输入值转换为无符号长整型值。如果输入参数为日期类型,\n 会将其值解析为自 Unix epoch 以来的毫秒数,并转换为无符号长整型值。\n 布尔值 *true* 将转换为无符号长整型值 *1**false* 转换为 *0*。\n\n ```\n ROW str1 = \"2147483648\", str2 = \"2147483648.2\", str3 = \"foo\"\n | EVAL long1 = TO_UNSIGNED_LONG(str1), long2 = TO_ULONG(str2), long3 = TO_UL(str3)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_upper": "TO_UPPER",
"languageDocumentationPopover.documentationESQL.to_upper.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_UPPER\n 返回一个新字符串,表示已将输入字符串转为大写。\n\n ```\n ROW message = \"Some Text\"\n | EVAL message_upper = TO_UPPER(message)\n ```\n ",
"languageDocumentationPopover.documentationESQL.to_version": "TO_VERSION",
"languageDocumentationPopover.documentationESQL.to_version.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TO_VERSION\n 将输入字符串转换为版本值。\n\n ```\n ROW v = TO_VERSION(\"1.2.3\")\n ```\n ",
"languageDocumentationPopover.documentationESQL.trim": "TRIM",
"languageDocumentationPopover.documentationESQL.trim.markdown": "<!--\n This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.\n -->\n\n ### TRIM\n 从字符串中移除前导和尾随空格。\n\n ```\n ROW message = \" some text \", color = \" red \"\n | EVAL message = TRIM(message)\n | EVAL color = TRIM(color)\n ```\n ",
"languageDocumentationPopover.documentationESQL.where": "WHERE",
"languageDocumentationPopover.documentationESQL.where.markdown": "### WHERE\n使用 `WHERE` 可生成一个表,其中包含输入表中所提供的条件评估为 `true` 的所有行:\n \n```\nFROM employees\n| KEEP first_name, last_name, still_hired\n| WHERE still_hired == true\n```\n\n#### 运算符\n\n请参阅**运算符**了解所支持的运算符的概览。\n\n#### 函数\n`WHERE` 支持各种用于计算值的函数。请参阅**函数**了解更多信息。\n ",
"textBasedEditor.query.textBasedLanguagesEditor.EnableWordWrapLabel": "在管道符上添加换行符",
"textBasedEditor.query.textBasedLanguagesEditor.errorCount": "{count} 个{count, plural, other {错误}}",
"textBasedEditor.query.textBasedLanguagesEditor.errorsTitle": "错误",
"textBasedEditor.query.textBasedLanguagesEditor.esql": "ES|QL",
"textBasedEditor.query.textBasedLanguagesEditor.expandLabel": "展开",
"textBasedEditor.query.textBasedLanguagesEditor.feedback": "反馈",
"textBasedEditor.query.textBasedLanguagesEditor.functions": "函数",
"textBasedEditor.query.textBasedLanguagesEditor.functionsDocumentationESQLDescription": "ROW、EVAL 和 WHERE 支持的函数。",
"textBasedEditor.query.textBasedLanguagesEditor.groupingFunctions": "分组函数",
"textBasedEditor.query.textBasedLanguagesEditor.groupingFunctionsDocumentationESQLDescription": "这些分组函数可以与 `STATS...BY` 搭配使用:",
"languageDocumentationPopover.documentationESQL.functions": "函数",
"languageDocumentationPopover.documentationESQL.functionsDocumentationESQLDescription": "ROW、EVAL 和 WHERE 支持的函数。",
"languageDocumentationPopover.documentationESQL.groupingFunctions": "分组函数",
"languageDocumentationPopover.documentationESQL.groupingFunctionsDocumentationESQLDescription": "这些分组函数可以与 `STATS...BY` 搭配使用:",
"textBasedEditor.query.textBasedLanguagesEditor.hideQueriesLabel": "隐藏最近查询",
"textBasedEditor.query.textBasedLanguagesEditor.lineCount": "{count} {count, plural, other {行}}",
"textBasedEditor.query.textBasedLanguagesEditor.lineNumber": "第 {lineNumber} 行",
"textBasedEditor.query.textBasedLanguagesEditor.operators": "运算符",
"textBasedEditor.query.textBasedLanguagesEditor.operatorsDocumentationESQLDescription": "ES|QL 支持以下运算符:",
"textBasedEditor.query.textBasedLanguagesEditor.processingCommands": "处理命令",
"textBasedEditor.query.textBasedLanguagesEditor.processingCommandsDescription": "处理命令会通过添加、移除或更改行和列来更改输入表。ES|QL 支持以下处理命令。",
"languageDocumentationPopover.documentationESQL.operators": "运算符",
"languageDocumentationPopover.documentationESQL.operatorsDocumentationESQLDescription": "ES|QL 支持以下运算符:",
"languageDocumentationPopover.documentationESQL.processingCommands": "处理命令",
"languageDocumentationPopover.documentationESQL.processingCommandsDescription": "处理命令会通过添加、移除或更改行和列来更改输入表。ES|QL 支持以下处理命令。",
"textBasedEditor.query.textBasedLanguagesEditor.querieshistory.error": "查询失败",
"textBasedEditor.query.textBasedLanguagesEditor.querieshistory.success": "已成功运行查询",
"textBasedEditor.query.textBasedLanguagesEditor.querieshistoryCopy": "复制查询到剪贴板",
@ -7347,7 +7345,7 @@
"textBasedEditor.query.textBasedLanguagesEditor.recentQueriesColumnLabel": "最近查询",
"textBasedEditor.query.textBasedLanguagesEditor.runQuery": "运行查询",
"textBasedEditor.query.textBasedLanguagesEditor.showQueriesLabel": "显示最近查询",
"textBasedEditor.query.textBasedLanguagesEditor.sourceCommands": "源命令",
"languageDocumentationPopover.documentationESQL.sourceCommands": "源命令",
"textBasedEditor.query.textBasedLanguagesEditor.submitFeedback": "提交反馈",
"textBasedEditor.query.textBasedLanguagesEditor.timeRanColumnLabel": "运行时间",
"textBasedEditor.query.textBasedLanguagesEditor.timestampNotDetected": "未找到 @timestamp",