// Importación de ForceGraph3D import ForceGraph3D from './libs/3d-force-graph.min.js'; // Asegúrate de que está en la carpeta libs // Importación del cliente de Elasticsearch import { Client } from 'https://cdn.skypack.dev/@elastic/elasticsearch'; // Configuración de la conexión a Elasticsearch const client = new Client({ node: 'http://localhost:9200' }); // Definir la clase Graph class Graph { constructor(containerId) { this.graph = ForceGraph3D()(document.getElementById(containerId)); this.maxNodes = 200; // Número máximo de nodos a mostrar this.minSimilarity = 5; // Umbral mínimo de similitud } // Configuración del número máximo de nodos setMaxNodes(maxNodes) { this.maxNodes = maxNodes; } // Configuración del umbral de similitud setMinSimilarity(minSimilarity) { this.minSimilarity = minSimilarity; } // Cargar nodos desde Elasticsearch async loadNodes(subtematica = '', palabraClave = '', fechaInicio = '', fechaFin = '') { const query = { bool: { must: [ { match: { tema: 'corporaciones y organizaciones internacionales' } } ], filter: [] } }; if (subtematica) { query.bool.must.push({ match: { subtema: subtematica } }); } if (palabraClave) { query.bool.must.push({ match: { contenido: palabraClave } }); } if (fechaInicio && fechaFin) { query.bool.filter.push({ range: { fecha: { gte: fechaInicio, lte: fechaFin } } }); } const response = await client.search({ index: 'informacion', // Usamos el índice correcto body: { query: query, size: this.maxNodes, sort: { importancia: 'desc' } } }); return response.body.hits.hits.map(hit => ({ id: hit._source.nombre_archivo, group: hit._source.tipo_archivo, tema: hit._source.tema, content: hit._source.contenido, fecha: hit._source.fecha })); } // Cargar relaciones directamente desde Elasticsearch async loadLinks() { const response = await client.search({ index: 'informacion', // Asegurarse de que el índice correcto se utiliza para las relaciones body: { query: { match_all: {} // Obtenemos todas las relaciones almacenadas }, size: this.maxNodes // Limitamos el tamaño de la respuesta } }); const links = response.body.hits.hits.map(hit => { const content = hit._source.contenido; const lines = content.split('\n'); // Asumiendo que las relaciones están en formato línea por línea return lines.map(line => { const [source, target, similarity] = line.split(','); if (parseFloat(similarity) >= this.minSimilarity) { return { source: path.basename(source.trim(), '.txt'), target: path.basename(target.trim(), '.txt'), value: parseFloat(similarity) }; } }).filter(link => link); // Filtramos los enlaces válidos }); return links.flat(); } // Crear datos del gráfico createGraphData(nodes, links) { return { nodes, links }; } // Mostrar el contenido de un nodo al hacer clic async showNodeContent(node) { try { const response = await client.search({ index: 'informacion', body: { query: { match: { nombre_archivo: node.id } } }, size: 1 }); const content = response.body.hits.hits[0]._source.contenido; const contentDiv = document.getElementById('contentDisplay'); contentDiv.innerText = content || "No hay contenido disponible."; } catch (error) { console.error("Error al obtener contenido:", error); const contentDiv = document.getElementById('contentDisplay'); contentDiv.innerText = "Error al obtener contenido."; } } // Dibujar el gráfico async drawGraph(subtematica = '', palabraClave = '', fechaInicio = '', fechaFin = '') { const nodes = await this.loadNodes(subtematica, palabraClave, fechaInicio, fechaFin); const links = await this.loadLinks(); // Cargamos las relaciones desde Elasticsearch const graphData = this.createGraphData(nodes, links); this.graph .graphData(graphData) .backgroundColor('black') .nodeLabel('id') .nodeAutoColorBy('group') .nodeVal(5) .linkColor(() => 'yellow') .onNodeClick(node => { this.showNodeContent(node); }) .forceEngine('d3') .d3Force('charge').strength(-200) .d3Force('link').distance(50); } } // Inicializar el gráfico const myGraph = new Graph('canvasContainer'); myGraph.drawGraph();