From a61333aeeb947036edbea0a06788d4861cb2d71a Mon Sep 17 00:00:00 2001 From: David Snelling Date: Thu, 14 Aug 2025 09:58:19 -0700 Subject: [PATCH] feat: Add per-service statistics and field discovery to CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 ENHANCED STATISTICS DISPLAY: - Show per-service breakdown of nouns, verbs, metadata - Display serviceBreakdown from getStatistics() properly - Beautiful formatting for multi-service environments 🔍 FIELD DISCOVERY FOR ADVANCED SEARCH: - New section in 'brainy status' shows available filter fields - Added --fields option to search command - Usage examples provided for complex filtering - Integrates with getFilterFields() method 📊 USAGE EXAMPLES: - brainy status (shows per-service stats + available fields) - brainy search 'query' --fields (field discovery) - brainy search 'query' --filter '{"type":"person"}' (advanced filtering) Perfect for developers doing complex queries and multi-service deployments! --- bin/brainy.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/bin/brainy.js b/bin/brainy.js index 63373cc7..44826175 100755 --- a/bin/brainy.js +++ b/bin/brainy.js @@ -134,14 +134,46 @@ program } })) -// Command 3: SEARCH - Triple-power search +// Command 3: SEARCH - Triple-power search program .command('search ') .description('Search your brain (vector + graph + facets)') .option('-l, --limit ', 'Results limit', '10') - .option('-f, --filter ', 'Metadata filters') + .option('-f, --filter ', 'Metadata filters (see "brainy fields" for available fields)') .option('-d, --depth ', 'Relationship depth', '2') + .option('--fields', 'Show available filter fields and exit') .action(wrapAction(async (query, options) => { + + // Handle --fields option + if (options.fields) { + console.log(colors.primary('🔍 Available Filter Fields')) + console.log(colors.primary('=' .repeat(30))) + + try { + const { BrainyData } = await import('../dist/brainyData.js') + const brainy = new BrainyData() + await brainy.init() + + const filterFields = await brainy.getFilterFields() + if (filterFields.length > 0) { + console.log(colors.success('Available fields for --filter option:')) + filterFields.forEach(field => { + console.log(colors.info(` ${field}`)) + }) + console.log() + console.log(colors.primary('Usage Examples:')) + console.log(colors.info(` brainy search "query" --filter '{"type":"person"}'`)) + console.log(colors.info(` brainy search "query" --filter '{"category":"work","status":"active"}'`)) + } else { + console.log(colors.warning('No indexed fields available yet.')) + console.log(colors.info('Add some data with metadata to see available fields.')) + } + + } catch (error) { + console.log(colors.error(`Error: ${error.message}`)) + } + return + } console.log(colors.info(`🔍 Searching: "${query}"`)) const searchOptions = { @@ -212,9 +244,21 @@ program console.log(colors.info(` Total Items: ${colors.success(stats.total || 0)}`)) console.log(colors.info(` Nouns: ${colors.success(stats.nounCount || 0)}`)) console.log(colors.info(` Verbs (Relationships): ${colors.success(stats.verbCount || 0)}`)) - console.log(colors.info(` Documents: ${colors.success(stats.documentCount || 0)}`)) + console.log(colors.info(` Metadata Records: ${colors.success(stats.metadataCount || 0)}`)) console.log() + // Per-Service Breakdown (if available) + if (stats.serviceBreakdown && Object.keys(stats.serviceBreakdown).length > 0) { + console.log(colors.primary('🔧 Per-Service Breakdown')) + Object.entries(stats.serviceBreakdown).forEach(([service, serviceStats]) => { + console.log(colors.info(` ${colors.success(service)}:`)) + console.log(colors.info(` Nouns: ${serviceStats.nounCount}`)) + console.log(colors.info(` Verbs: ${serviceStats.verbCount}`)) + console.log(colors.info(` Metadata: ${serviceStats.metadataCount}`)) + }) + console.log() + } + // Storage Information if (stats.storage) { console.log(colors.primary('💾 Storage Information')) @@ -291,6 +335,25 @@ program console.log() } + // Available Fields for Advanced Search + console.log(colors.primary('🔍 Available Search Fields')) + try { + const filterFields = await brainy.getFilterFields() + if (filterFields.length > 0) { + console.log(colors.info(' Use these fields for advanced filtering:')) + filterFields.forEach(field => { + console.log(colors.success(` ${field}`)) + }) + console.log(colors.info('\n Example: brainy search "query" --filter \'{"type":"person"}\'')) + } else { + console.log(colors.warning(' No indexed fields available yet')) + console.log(colors.info(' Add some data to see available fields')) + } + } catch (error) { + console.log(colors.warning(' Field discovery not available')) + } + console.log() + // Show raw JSON if verbose if (options.verbose) { console.log(colors.primary('📋 Raw Statistics (JSON)'))