feat(esmole): mapping flatten
This commit is contained in:
1 parent
7381db1189
commit
b2a9c3323f
2 files changed
+77
No files matched your search
@@ -0,0 +1,37 @@
|
|||||||
|
export type MappingRow = { index?: string; field: string; type: string }
|
||||||
|
|
||||||
|
type Props = Record<string, { type?: string; properties?: Props; fields?: Props }>
|
||||||
|
|
||||||
|
const walk = (props: Props, prefix: string, rows: MappingRow[], index?: string): void => {
|
||||||
|
for (const [name, def] of Object.entries(props)) {
|
||||||
|
const field = prefix ? prefix + '.' + name : name
|
||||||
|
if (def.type) {
|
||||||
|
rows.push(index ? { index, field, type: def.type } : { field, type: def.type })
|
||||||
|
}
|
||||||
|
if (def.fields) {
|
||||||
|
walk(def.fields, field, rows, index)
|
||||||
|
}
|
||||||
|
if (def.properties) {
|
||||||
|
walk(def.properties, field, rows, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flattens an ES `GET /{index}/_mapping` response into dotted field:type rows.
|
||||||
|
// With a single index the `index` key is omitted; with multiple indices each
|
||||||
|
// row carries its index name.
|
||||||
|
export const flattenMapping = (raw: unknown): MappingRow[] => {
|
||||||
|
const rows: MappingRow[] = []
|
||||||
|
if (typeof raw !== 'object' || raw === null) {
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
const indices = Object.entries(raw as Record<string, { mappings?: { properties?: Props } }>)
|
||||||
|
const multi = indices.length > 1
|
||||||
|
for (const [indexName, body] of indices) {
|
||||||
|
const props = body?.mappings?.properties
|
||||||
|
if (props) {
|
||||||
|
walk(props, '', rows, multi ? indexName : undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { flattenMapping } from '../../../src/es/mapping.js'
|
||||||
|
|
||||||
|
const raw = {
|
||||||
|
myindex: {
|
||||||
|
mappings: {
|
||||||
|
properties: {
|
||||||
|
id: { type: 'keyword' },
|
||||||
|
title: { type: 'text', fields: { raw: { type: 'keyword' } } },
|
||||||
|
author: { properties: { name: { type: 'text' }, age: { type: 'integer' } } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('flattenMapping', () => {
|
||||||
|
it('flattens nested properties to dotted field:type rows', () => {
|
||||||
|
const rows = flattenMapping(raw)
|
||||||
|
expect(rows).toContainEqual({ field: 'id', type: 'keyword' })
|
||||||
|
expect(rows).toContainEqual({ field: 'title', type: 'text' })
|
||||||
|
expect(rows).toContainEqual({ field: 'title.raw', type: 'keyword' })
|
||||||
|
expect(rows).toContainEqual({ field: 'author.name', type: 'text' })
|
||||||
|
expect(rows).toContainEqual({ field: 'author.age', type: 'integer' })
|
||||||
|
})
|
||||||
|
it('handles multiple indices by prefixing the index name', () => {
|
||||||
|
const rows = flattenMapping({
|
||||||
|
a: { mappings: { properties: { x: { type: 'long' } } } },
|
||||||
|
b: { mappings: { properties: { y: { type: 'date' } } } }
|
||||||
|
})
|
||||||
|
expect(rows).toContainEqual({ index: 'a', field: 'x', type: 'long' })
|
||||||
|
expect(rows).toContainEqual({ index: 'b', field: 'y', type: 'date' })
|
||||||
|
})
|
||||||
|
it('returns empty array for an empty mapping', () => {
|
||||||
|
expect(flattenMapping({ idx: { mappings: {} } })).toEqual([])
|
||||||
|
})
|
||||||
|
it('returns empty array for a non-object input', () => {
|
||||||
|
expect(flattenMapping(null)).toEqual([])
|
||||||
|
expect(flattenMapping('nope')).toEqual([])
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in new issue
Block a user