AIdeaText commited on
Commit
c9030f8
·
verified ·
1 Parent(s): ba373aa

Update modules/database/semantic_mongo_live_db.py

Browse files
modules/database/semantic_mongo_live_db.py CHANGED
@@ -2,63 +2,115 @@
2
  import logging
3
  from datetime import datetime, timezone
4
  import base64
 
 
5
 
6
- # Importaciones locales
7
- from .mongo_db import get_collection, insert_document, find_documents
8
-
9
  logger = logging.getLogger(__name__)
10
  COLLECTION_NAME = 'student_semantic_live_analysis'
11
 
12
  def store_student_semantic_live_result(username, text, analysis_result, lang_code='en'):
13
  """
14
  Guarda el resultado del análisis semántico en vivo en MongoDB.
 
15
  """
16
  try:
17
- if not username or not text or not analysis_result:
18
- logger.error("Datos insuficientes para guardar el análisis")
 
 
 
 
 
19
  return False
20
 
21
- # Preparar el gráfico conceptual
 
 
 
 
22
  concept_graph_data = None
23
  if 'concept_graph' in analysis_result and analysis_result['concept_graph'] is not None:
24
  try:
25
- if isinstance(analysis_result['concept_graph'], bytes):
26
- concept_graph_data = base64.b64encode(analysis_result['concept_graph']).decode('utf-8')
 
 
 
 
 
 
 
 
 
27
  else:
28
- logger.warning("El gráfico conceptual no está en formato bytes")
29
  except Exception as e:
30
- logger.error(f"Error al codificar gráfico conceptual: {str(e)}")
 
31
 
32
- # Crear documento para MongoDB
33
  analysis_document = {
34
  'username': username,
35
  'timestamp': datetime.now(timezone.utc),
36
- 'text': text,
37
  'analysis_type': 'semantic_live',
38
- 'key_concepts': analysis_result.get('key_concepts', []),
39
- 'concept_centrality': analysis_result.get('concept_centrality', {}),
40
- 'concept_graph': concept_graph_data,
41
- 'language': lang_code
 
42
  }
43
 
44
- # Insertar en MongoDB
45
- result = insert_document(COLLECTION_NAME, analysis_document)
46
- if result:
47
- logger.info(f"Análisis semántico en vivo guardado para {username}")
48
- return True
49
-
50
- logger.error("No se pudo insertar el documento en MongoDB")
51
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  except Exception as e:
54
- logger.error(f"Error al guardar el análisis semántico en vivo: {str(e)}")
55
  return False
56
 
57
  def get_student_semantic_live_analysis(username, limit=10):
58
  """
59
  Recupera los análisis semánticos en vivo de un estudiante.
 
60
  """
61
  try:
 
 
 
 
 
 
 
 
 
62
  query = {
63
  "username": username,
64
  "analysis_type": "semantic_live"
@@ -66,25 +118,42 @@ def get_student_semantic_live_analysis(username, limit=10):
66
 
67
  projection = {
68
  "timestamp": 1,
69
- "text": 1,
70
- "key_concepts": 1,
71
  "concept_graph": 1,
72
- "_id": 1
 
73
  }
74
 
75
- results = find_documents(
76
- COLLECTION_NAME,
77
- query,
78
- projection=projection,
79
- sort=[("timestamp", -1)],
80
- limit=limit
81
- )
82
-
83
- logger.info(f"Recuperados {len(results)} análisis semánticos en vivo para {username}")
84
- return results
85
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  except Exception as e:
87
- logger.error(f"Error recuperando análisis semántico en vivo: {str(e)}")
88
  return []
89
 
90
  __all__ = [
 
2
  import logging
3
  from datetime import datetime, timezone
4
  import base64
5
+ from bson import Binary
6
+ from pymongo.errors import PyMongoError
7
 
8
+ # Configuración del logger
 
 
9
  logger = logging.getLogger(__name__)
10
  COLLECTION_NAME = 'student_semantic_live_analysis'
11
 
12
  def store_student_semantic_live_result(username, text, analysis_result, lang_code='en'):
13
  """
14
  Guarda el resultado del análisis semántico en vivo en MongoDB.
15
+ Versión mejorada con manejo robusto de errores y verificación de datos.
16
  """
17
  try:
18
+ # 1. Validación exhaustiva de los parámetros de entrada
19
+ if not username or not isinstance(username, str):
20
+ logger.error("Nombre de usuario inválido o vacío")
21
+ return False
22
+
23
+ if not text or not isinstance(text, str):
24
+ logger.error("Texto de análisis inválido o vacío")
25
  return False
26
 
27
+ if not analysis_result or not isinstance(analysis_result, dict):
28
+ logger.error("Resultado de análisis inválido o vacío")
29
+ return False
30
+
31
+ # 2. Preparación del gráfico conceptual con múltiples formatos soportados
32
  concept_graph_data = None
33
  if 'concept_graph' in analysis_result and analysis_result['concept_graph'] is not None:
34
  try:
35
+ graph_data = analysis_result['concept_graph']
36
+
37
+ if isinstance(graph_data, bytes):
38
+ # Codificar a base64 para almacenamiento eficiente
39
+ concept_graph_data = base64.b64encode(graph_data).decode('utf-8')
40
+ elif isinstance(graph_data, str):
41
+ # Si ya es string (base64), usarlo directamente
42
+ concept_graph_data = graph_data
43
+ elif isinstance(graph_data, Binary):
44
+ # Si es Binary de pymongo, convertirlo
45
+ concept_graph_data = base64.b64encode(graph_data).decode('utf-8')
46
  else:
47
+ logger.warning(f"Formato de gráfico no soportado: {type(graph_data)}")
48
  except Exception as e:
49
+ logger.error(f"Error al procesar gráfico conceptual: {str(e)}", exc_info=True)
50
+ # Continuar sin gráfico en lugar de fallar completamente
51
 
52
+ # 3. Preparación del documento con validación de campos
53
  analysis_document = {
54
  'username': username,
55
  'timestamp': datetime.now(timezone.utc),
56
+ 'text': text[:10000], # Limitar tamaño para prevenir documentos muy grandes
57
  'analysis_type': 'semantic_live',
58
+ 'language': lang_code,
59
+ 'metadata': {
60
+ 'version': '1.0',
61
+ 'source': 'live_interface'
62
+ }
63
  }
64
 
65
+ # Campos opcionales con validación
66
+ if 'key_concepts' in analysis_result and isinstance(analysis_result['key_concepts'], list):
67
+ analysis_document['key_concepts'] = analysis_result['key_concepts'][:50] # Limitar a 50 conceptos
68
+
69
+ if 'concept_centrality' in analysis_result and isinstance(analysis_result['concept_centrality'], dict):
70
+ analysis_document['concept_centrality'] = analysis_result['concept_centrality']
71
+
72
+ if concept_graph_data:
73
+ analysis_document['concept_graph'] = concept_graph_data
74
+
75
+ # 4. Operación de base de datos con manejo de errores específico
76
+ try:
77
+ collection = get_collection(COLLECTION_NAME)
78
+ if not collection:
79
+ logger.error("No se pudo obtener la colección MongoDB")
80
+ return False
81
+
82
+ result = collection.insert_one(analysis_document)
83
+
84
+ if result.inserted_id:
85
+ logger.info(f"Análisis guardado exitosamente para {username}. ID: {result.inserted_id}")
86
+ return True
87
+
88
+ logger.error("La operación de inserción no devolvió un ID")
89
+ return False
90
+
91
+ except PyMongoError as mongo_error:
92
+ logger.error(f"Error de MongoDB al guardar análisis: {str(mongo_error)}", exc_info=True)
93
+ return False
94
 
95
  except Exception as e:
96
+ logger.error(f"Error inesperado al guardar análisis: {str(e)}", exc_info=True)
97
  return False
98
 
99
  def get_student_semantic_live_analysis(username, limit=10):
100
  """
101
  Recupera los análisis semánticos en vivo de un estudiante.
102
+ Versión mejorada con paginación y manejo de errores.
103
  """
104
  try:
105
+ # Validación de parámetros
106
+ if not username or not isinstance(username, str):
107
+ logger.error("Nombre de usuario inválido para recuperación")
108
+ return []
109
+
110
+ if not isinstance(limit, int) or limit <= 0:
111
+ limit = 10 # Valor por defecto si el límite es inválido
112
+
113
+ # Consulta con proyección para optimizar transferencia
114
  query = {
115
  "username": username,
116
  "analysis_type": "semantic_live"
 
118
 
119
  projection = {
120
  "timestamp": 1,
121
+ "text": {"$substr": ["$text", 0, 200]}, # Solo primeros 200 caracteres
122
+ "key_concepts": {"$slice": ["$key_concepts", 10]}, # Solo primeros 10 conceptos
123
  "concept_graph": 1,
124
+ "_id": 1,
125
+ "metadata": 1
126
  }
127
 
128
+ # Operación de base de datos con manejo de errores
129
+ try:
130
+ collection = get_collection(COLLECTION_NAME)
131
+ if not collection:
132
+ logger.error("No se pudo obtener la colección MongoDB")
133
+ return []
134
+
135
+ cursor = collection.find(query, projection).sort("timestamp", -1).limit(limit)
136
+ results = list(cursor)
137
+
138
+ # Post-procesamiento para asegurar formato consistente
139
+ for doc in results:
140
+ if 'concept_graph' in doc and isinstance(doc['concept_graph'], str):
141
+ try:
142
+ # Convertir base64 string a bytes para compatibilidad
143
+ doc['concept_graph'] = base64.b64decode(doc['concept_graph'])
144
+ except Exception as e:
145
+ logger.warning(f"Error al decodificar gráfico: {str(e)}")
146
+ doc.pop('concept_graph', None)
147
+
148
+ logger.info(f"Recuperados {len(results)} análisis para {username}")
149
+ return results
150
+
151
+ except PyMongoError as mongo_error:
152
+ logger.error(f"Error de MongoDB al recuperar análisis: {str(mongo_error)}")
153
+ return []
154
+
155
  except Exception as e:
156
+ logger.error(f"Error inesperado al recuperar análisis: {str(e)}", exc_info=True)
157
  return []
158
 
159
  __all__ = [