Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Search][Onboarding] improve sample documents (#196772) #196956

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions x-pack/plugins/search_indices/public/code_examples/curl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,19 @@ export const CurlCreateIndexExamples: CreateIndexLanguageExamples = {
};

export const CurlVectorsIngestDataExample: IngestDataCodeDefinition = {
ingestCommand: ({
elasticsearchURL,
apiKey,
indexName,
sampleDocument,
}) => `curl -X POST "${elasticsearchURL}/_bulk?pretty" \
ingestCommand: ({ elasticsearchURL, apiKey, indexName, sampleDocuments }) => {
let result = `curl -X POST "${elasticsearchURL}/_bulk?pretty" \
--header 'Authorization: ApiKey ${apiKey ?? API_KEY_PLACEHOLDER}' \
--header 'Content-Type: application/json' \
-d'
{ "index": { "_index": "${indexName}" } }
${JSON.stringify(sampleDocument)}
`,
-d'`;
sampleDocuments.forEach((document) => {
result += `
{ "index" : { "_index" : "${indexName}" } }
${JSON.stringify(document)}`;
});
result += "\n'";
return result;
},
updateMappingsCommand: ({
elasticsearchURL,
apiKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const JSServerlessIngestVectorDataExample: IngestDataCodeDefinition = {
ingestCommand: ({
apiKey,
elasticsearchURL,
sampleDocument,
sampleDocuments,
indexName,
}) => `import { Client } from "@elastic/elasticsearch";

Expand All @@ -85,9 +85,7 @@ const client = new Client({
});

const index = "${indexName}";
const docs = [
${JSON.stringify(sampleDocument, null, 2)},
]
const docs = ${JSON.stringify(sampleDocuments, null, 2)};

const bulkIngestResponse = await client.helpers.bulk({
index,
Expand Down
6 changes: 2 additions & 4 deletions x-pack/plugins/search_indices/public/code_examples/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const serverlessIngestionCommand: IngestCodeSnippetFunction = ({
elasticsearchURL,
apiKey,
indexName,
sampleDocument,
sampleDocuments,
}) => `from elasticsearch import Elasticsearch, helpers

client = Elasticsearch(
Expand All @@ -81,9 +81,7 @@ client = Elasticsearch(

index_name = "${indexName}"

docs = [
${JSON.stringify(sampleDocument, null, 4)},
]
docs = ${JSON.stringify(sampleDocuments, null, 4)}

bulk_response = helpers.bulk(client, docs, index=index_name)
print(bulk_response)`;
Expand Down
13 changes: 9 additions & 4 deletions x-pack/plugins/search_indices/public/code_examples/sense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ export const ConsoleCreateIndexExamples: CreateIndexLanguageExamples = {
};

export const ConsoleVectorsIngestDataExample: IngestDataCodeDefinition = {
ingestCommand: ({ indexName, sampleDocument }) => `POST /_bulk?pretty
{ "index": { "_index": "${indexName}" } }
${JSON.stringify(sampleDocument)}
`,
ingestCommand: ({ indexName, sampleDocuments }) => {
let result = 'POST /_bulk?pretty\n';
sampleDocuments.forEach((document) => {
result += `{ "index": { "_index": "${indexName}" } }
${JSON.stringify(document)}`;
});
result += '\n';
return result;
},
updateMappingsCommand: ({ indexName, mappingProperties }) => `PUT /${indexName}/_mapping
${JSON.stringify({ properties: mappingProperties }, null, 2)}`,
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,25 @@ export const AddDocumentsCodeExample = ({
},
[usageTracker]
);
const sampleDocument = useMemo(() => {
// TODO: implement smart document generation
return generateSampleDocument(codeSampleMappings);
const sampleDocuments = useMemo(() => {
return [1, 2, 3].map((num) =>
generateSampleDocument(codeSampleMappings, `Example text ${num}`)
);
}, [codeSampleMappings]);
const { apiKey, apiKeyIsVisible } = useSearchApiKey();
const codeParams: IngestCodeSnippetParameters = useMemo(() => {
return {
indexName,
elasticsearchURL: elasticsearchUrl,
sampleDocument,
sampleDocuments,
indexHasMappings,
mappingProperties: codeSampleMappings,
apiKey: apiKeyIsVisible && apiKey ? apiKey : undefined,
};
}, [
indexName,
elasticsearchUrl,
sampleDocument,
sampleDocuments,
codeSampleMappings,
indexHasMappings,
apiKeyIsVisible,
Expand All @@ -95,22 +96,20 @@ export const AddDocumentsCodeExample = ({
onSelectLanguage={onSelectLanguage}
/>
</EuiFlexItem>
{selectedLanguage === 'curl' && (
<EuiFlexItem grow={false}>
<TryInConsoleButton
request={
!indexHasMappings
? `${ingestCodeExamples.sense.updateMappingsCommand(
codeParams
)}\n\n${ingestCodeExamples.sense.ingestCommand(codeParams)}`
: ingestCodeExamples.sense.ingestCommand(codeParams)
}
application={application}
sharePlugin={share}
consolePlugin={consolePlugin}
/>
</EuiFlexItem>
)}
<EuiFlexItem grow={false}>
<TryInConsoleButton
request={
!indexHasMappings
? `${ingestCodeExamples.sense.updateMappingsCommand(
codeParams
)}\n\n${ingestCodeExamples.sense.ingestCommand(codeParams)}`
: ingestCodeExamples.sense.ingestCommand(codeParams)
}
application={application}
sharePlugin={share}
consolePlugin={consolePlugin}
/>
</EuiFlexItem>
</EuiFlexGroup>
{selectedCodeExamples.installCommand && (
<EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,21 @@ export const CreateIndexCodeView = ({
onSelectLanguage={onSelectLanguage}
/>
</EuiFlexItem>
{selectedLanguage === 'curl' && (
<EuiFlexItem grow={false}>
<TryInConsoleButton
request={selectedCodeExamples.sense.createIndex(codeParams)}
application={application}
sharePlugin={share}
consolePlugin={consolePlugin}
telemetryId={`${selectedLanguage}_create_index`}
onClick={() => {
usageTracker.click([
AnalyticsEvents.startCreateIndexRunInConsole,
`${AnalyticsEvents.startCreateIndexRunInConsole}_${selectedLanguage}`,
]);
}}
/>
</EuiFlexItem>
)}
<EuiFlexItem grow={false}>
<TryInConsoleButton
request={selectedCodeExamples.sense.createIndex(codeParams)}
application={application}
sharePlugin={share}
consolePlugin={consolePlugin}
telemetryId={`${selectedLanguage}_create_index`}
onClick={() => {
usageTracker.click([
AnalyticsEvents.startCreateIndexRunInConsole,
`${AnalyticsEvents.startCreateIndexRunInConsole}_${selectedLanguage}`,
]);
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
{selectedCodeExample.installCommand && (
<CodeSample
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/search_indices/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export interface CreateIndexCodeExamples {

export interface IngestCodeSnippetParameters extends CodeSnippetParameters {
indexName: string;
sampleDocument: object;
sampleDocuments: object[];
mappingProperties: Record<string, MappingProperty>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,21 @@ describe('document generation util', () => {
expect(result).toEqual({
title: 'Sample text for title',
tags: 'sample-keyword-tags',
body: 'Hello World',
body: 'Sample text for body',
});
});

it('should support providing sample text', () => {
const mapping: Record<string, MappingProperty> = {
body: { type: 'semantic_text', inference_id: '.elser_model_2' },
title: { type: 'text' },
};

const result = generateSampleDocument(mapping, 'Testing sample text!');

expect(result).toEqual({
title: 'Testing sample text!',
body: 'Testing sample text!',
});
});

Expand Down Expand Up @@ -113,8 +127,8 @@ describe('document generation util', () => {
const result = generateSampleDocument(mapping);

expect(Array.isArray(result.embedding)).toBe(true);
expect((result.embedding as number[]).length!).toBe(21);
expect((result.embedding as number[])[20]).toBe('...');
expect((result.embedding as number[]).length!).toBe(11);
expect((result.embedding as number[])[10]).toBe('...');
});

it('should generate a sample document for sparse_vector fields', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@ import type {
} from '@elastic/elasticsearch/lib/api/types';

export function generateSampleDocument(
mappingProperties: Record<string, MappingProperty>
mappingProperties: Record<string, MappingProperty>,
sampleText?: string
): Record<string, unknown> {
const sampleDocument: Record<string, unknown> = {};

Object.entries(mappingProperties).forEach(([field, mapping]) => {
if ('type' in mapping) {
switch (mapping.type) {
case 'text':
sampleDocument[field] = `Sample text for ${field}`;
sampleDocument[field] = sampleText ?? `Sample text for ${field}`;
break;
case 'keyword':
sampleDocument[field] = `sample-keyword-${field}`;
break;
case 'semantic_text':
sampleDocument[field] = 'Hello World';
sampleDocument[field] = sampleText ?? `Sample text for ${field}`;
break;
case 'integer':
case 'long':
Expand Down Expand Up @@ -74,9 +75,9 @@ export function generateSampleDocument(
return sampleDocument;
}

function generateDenseVector(mapping: MappingDenseVectorProperty, maxDisplayDims = 20) {
function generateDenseVector(mapping: MappingDenseVectorProperty, maxDisplayDims = 10) {
// Limit the dimensions for better UI display
const dimension = Math.min(mapping?.dims ?? 20, maxDisplayDims);
const dimension = Math.min(mapping?.dims ?? 10, maxDisplayDims);

// Generate an array of random floating-point numbers
const denseVector: Array<number | string> = Array.from({ length: dimension }, () =>
Expand Down