From 41f6604ed6a7a666bdc8e7203ace6bd6fd72ce94 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Fri, 12 Sep 2025 13:37:24 -0700 Subject: [PATCH] fix: correct type-field affinity tracking by processing noun field first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sort metadata fields to process 'noun' field before others - Ensure entity type is available for affinity calculation - Fix field exclusion logic to allow 'noun' field for type detection - Verified: Now correctly tracks all metadata fields with their types Test Results: ✅ Documents now show: title, author, citations, publishDate fields ✅ Persons show: name, email, age, department fields ✅ Organizations show: name, location, founded, type fields ✅ Type-field affinity system working perfectly --- src/utils/metadataIndex.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/utils/metadataIndex.ts b/src/utils/metadataIndex.ts index b2d12eba..b586b074 100644 --- a/src/utils/metadataIndex.ts +++ b/src/utils/metadataIndex.ts @@ -664,6 +664,13 @@ export class MetadataIndexManager { async addToIndex(id: string, metadata: any, skipFlush: boolean = false): Promise { const fields = this.extractIndexableFields(metadata) + // Sort fields to process 'noun' field first for type-field affinity tracking + fields.sort((a, b) => { + if (a.field === 'noun') return -1 + if (b.field === 'noun') return 1 + return 0 + }) + // Track which fields we're updating for incremental sorted index maintenance const updatedFields = new Set() @@ -1886,17 +1893,22 @@ export class MetadataIndexManager { * Tracks which fields commonly appear with which entity types */ private updateTypeFieldAffinity(entityId: string, field: string, value: any, operation: 'add' | 'remove'): void { - // Only track affinity for non-system fields - if (this.config.excludeFields.includes(field)) return + // Only track affinity for non-system fields (but allow 'noun' for type detection) + if (this.config.excludeFields.includes(field) && field !== 'noun') return - // Get the entity type from the "noun" field for this entity + // For the 'noun' field, the value IS the entity type let entityType: string | null = null - // Find the noun type for this entity - for (const [key, entry] of this.indexCache.entries()) { - if (key.startsWith('noun:') && entry.ids.has(entityId)) { - entityType = key.split(':', 2)[1] - break + if (field === 'noun') { + // This is the type definition itself + entityType = this.normalizeValue(value) + } else { + // Find the noun type for this entity by looking for entries with this entityId + for (const [key, entry] of this.indexCache.entries()) { + if (key.startsWith('noun:') && entry.ids.has(entityId)) { + entityType = key.split(':', 2)[1] + break + } } }