feat(elasticsearch): add hit document view and field type detection

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-09-04 01:01:32 +08:00
1 parent 37dc74d9de
commit 0bdf232487
7 files changed
+205 -13

No files matched your search

@@ -287,6 +287,16 @@ const documentFilterFieldSearch = ref<Record<string, string>>({});
const documentFilterRules = ref<DocumentFilterRule[]>([]);
const appliedDocumentFilter = ref<Record<string, unknown> | null>(null);
const elasticsearchMappingFields = ref<ColumnInfo[]>([]);
function elasticsearchGridColumnTypesFor(columns: readonly string[]): string[] {
const mappingTypes = elasticsearchFieldTypes.value;
return columns.map((column) => {
// Elasticsearch metadata fields are not part of an index mapping, but they
// are textual identifiers in the document grid just like mapped keywords.
if (column === "_id" || column === "_routing" || column === "_type") return "keyword";
return mappingTypes.get(column) ?? "";
});
}
const elasticsearchGridColumnTypes = computed(() => elasticsearchGridColumnTypesFor(lastGridColumns.value));
const dynamodbTableDescription = ref<DynamoDbTableDescription | null>(null);
const dynamodbIndexName = ref("__table__");
const dynamodbPageCursors = ref<Array<string | undefined>>([undefined]);
@@ -419,10 +429,11 @@ function commitLoadedDocuments(nextDocuments: JsonRecord[], nextCopyDocuments: J
const gridResult = computed<QueryResult>(() => {
const docs = documents.value;
const columnTypes = documentStoreProvider.value.kind === "elasticsearch" ? elasticsearchGridColumnTypes.value : lastGridColumnTypes.value;
if (!docs.length) {
return {
columns: lastGridColumns.value,
column_types: lastGridColumnTypes.value,
column_types: columnTypes,
rows: [],
affected_rows: 0,
execution_time_ms: 0,
@@ -432,7 +443,7 @@ const gridResult = computed<QueryResult>(() => {
return {
columns: lastGridColumns.value,
column_types: lastGridColumnTypes.value,
column_types: columnTypes,
rows: gridRows.value,
mongo_documents: docs,
mongo_copy_documents: copyDocuments.value,
@@ -513,7 +524,7 @@ async function exportAllDocumentStoreDocuments(onProgress?: (info: { rowsExporte
const result = mongoDocumentsToQueryResult(exportedDocuments, performance.now() - exportStartedAt, totalRows ?? exportedDocuments.length, exportedCopyDocuments, totalRows !== null);
if (result.columns.length === 0) result.columns = gridResult.value.columns;
result.column_types = kind === "mongodb" ? mongoDocumentGridColumnTypes(exportedDocuments, result.columns) : undefined;
result.column_types = kind === "mongodb" ? mongoDocumentGridColumnTypes(exportedDocuments, result.columns) : kind === "elasticsearch" ? elasticsearchGridColumnTypesFor(result.columns) : undefined;
result.affected_rows = exportedDocuments.length;
result.truncated = (kind === "dynamodb" || kind === "elasticsearch") && !!cursor && exportedDocuments.length >= rowLimit;
result.has_more = result.truncated;
@@ -879,7 +890,7 @@ async function applyDocumentStructuredFilters() {
async function loadElasticsearchMappingFields() {
if (documentStoreProvider.value.kind !== "elasticsearch") return;
try {
elasticsearchMappingFields.value = await api.getColumns(props.connectionId, props.database, "", props.collection);
elasticsearchMappingFields.value = (await api.getColumns(props.connectionId, props.database, "", props.collection)) ?? [];
} catch {
elasticsearchMappingFields.value = [];
}
@@ -398,6 +398,33 @@ afterEach(() => {
});
describe("DocumentBrowser Elasticsearch field search", () => {
it("passes Elasticsearch mapping types through to the table grid", async () => {
app?.unmount();
backend.getColumns.mockResolvedValue([
{ name: "profile", data_type: "object" },
{ name: "profile.name", data_type: "keyword" },
{ name: "title", data_type: "text" },
]);
backend.documentFindDocuments.mockResolvedValue({
documents: [{ _id: "document-1", title: "Example", profile: { name: "Ada" } }],
raw_documents: [],
total: 1,
total_is_exact: true,
});
app = createApp(DocumentBrowser, {
connectionId: "connection-1",
database: "",
collection: "orders",
databaseType: "elasticsearch",
});
app.mount(root!);
await flushUi();
const types = JSON.parse(root!.querySelector<HTMLElement>("[data-testid='data-grid']")!.dataset.resultColumnTypes ?? "[]");
expect(types).toEqual(["keyword", "text", "object"]);
});
it("migrates hidden columns and passes a stable index layout scope without changing the query result", async () => {
app?.unmount();
const legacyScopeKey = documentGridColumnVisibilityScopeKey({