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

Update modules/database/semantic_mongo_live_db.py

Browse files
modules/database/semantic_mongo_live_db.py CHANGED
@@ -1,10 +1,18 @@
1
  # modules/database/semantic_mongo_live_db.py
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'
@@ -12,151 +20,163 @@ COLLECTION_NAME = 'student_semantic_live_analysis'
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"
117
  }
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__ = [
160
  'store_student_semantic_live_result',
161
- 'get_student_semantic_live_analysis'
 
 
 
162
  ]
 
1
  # modules/database/semantic_mongo_live_db.py
2
  import logging
 
3
  import base64
4
+ from datetime import datetime, timezone
5
  from pymongo.errors import PyMongoError
6
 
7
+ # Importaciones locales
8
+ from .mongo_db import (
9
+ get_collection,
10
+ insert_document,
11
+ find_documents,
12
+ update_document,
13
+ delete_document
14
+ )
15
+
16
  # Configuración del logger
17
  logger = logging.getLogger(__name__)
18
  COLLECTION_NAME = 'student_semantic_live_analysis'
 
20
  def store_student_semantic_live_result(username, text, analysis_result, lang_code='en'):
21
  """
22
  Guarda el resultado del análisis semántico en vivo en MongoDB.
23
+ Versión mejorada con validación de datos y manejo de errores.
24
  """
25
  try:
26
+ # Validación de parámetros
27
  if not username or not isinstance(username, str):
28
+ logger.error("Nombre de usuario inválido")
29
  return False
30
 
31
  if not text or not isinstance(text, str):
32
+ logger.error("Texto de análisis inválido")
33
  return False
34
 
35
  if not analysis_result or not isinstance(analysis_result, dict):
36
+ logger.error("Resultado de análisis inválido")
37
  return False
38
 
39
+ # Preparar el gráfico conceptual
40
  concept_graph_data = None
41
+ if 'concept_graph' in analysis_result and analysis_result['concept_graph']:
42
  try:
43
+ if isinstance(analysis_result['concept_graph'], bytes):
44
+ concept_graph_data = base64.b64encode(analysis_result['concept_graph']).decode('utf-8')
45
+ elif isinstance(analysis_result['concept_graph'], str):
46
+ # Verificar si ya está en base64
47
+ concept_graph_data = analysis_result['concept_graph']
 
 
 
 
 
 
 
 
48
  except Exception as e:
49
+ logger.error(f"Error al procesar gráfico: {str(e)}")
 
50
 
51
+ # Crear documento con campos validados
52
  analysis_document = {
53
  'username': username,
54
  'timestamp': datetime.now(timezone.utc),
55
+ 'text': text[:50000], # Limitar tamaño
56
  'analysis_type': 'semantic_live',
57
  'language': lang_code,
58
+ 'key_concepts': analysis_result.get('key_concepts', [])[:50], # Limitar a 50 conceptos
59
+ 'concept_centrality': analysis_result.get('concept_centrality', {}),
60
  'metadata': {
61
  'version': '1.0',
62
  'source': 'live_interface'
63
  }
64
  }
65
 
 
 
 
 
 
 
 
66
  if concept_graph_data:
67
  analysis_document['concept_graph'] = concept_graph_data
68
 
69
+ # Operación de base de datos
70
  try:
71
+ result = insert_document(COLLECTION_NAME, analysis_document)
72
+ if result:
73
+ logger.info(f"Análisis en vivo guardado para {username}")
 
 
 
 
 
 
74
  return True
75
+ logger.error("Inserción fallida (sin ID devuelto)")
 
76
  return False
77
+ except PyMongoError as e:
78
+ logger.error(f"Error de MongoDB: {str(e)}")
 
79
  return False
80
 
81
  except Exception as e:
82
+ logger.error(f"Error inesperado: {str(e)}", exc_info=True)
83
  return False
84
 
85
  def get_student_semantic_live_analysis(username, limit=10):
86
  """
87
  Recupera los análisis semánticos en vivo de un estudiante.
88
+ Versión corregida con consulta adecuada.
89
  """
90
  try:
 
 
 
 
 
 
 
 
 
91
  query = {
92
  "username": username,
93
+ "analysis_type": "semantic_live" # Corregido a semantic_live
94
  }
95
 
96
  projection = {
97
  "timestamp": 1,
98
+ "text": {"$substr": ["$text", 0, 200]}, # Solo primeros 200 chars
99
+ "key_concepts": 1,
100
  "concept_graph": 1,
101
+ "_id": 1
 
102
  }
103
 
104
+ results = find_documents(
105
+ COLLECTION_NAME,
106
+ query,
107
+ projection=projection,
108
+ sort=[("timestamp", -1)],
109
+ limit=limit
110
+ )
111
+
112
+ logger.info(f"Recuperados {len(results)} análisis en vivo para {username}")
113
+ return results
114
+
115
+ except PyMongoError as e:
116
+ logger.error(f"Error de MongoDB: {str(e)}")
117
+ return []
118
+ except Exception as e:
119
+ logger.error(f"Error inesperado: {str(e)}")
120
+ return []
121
 
122
+ def update_student_semantic_live_analysis(analysis_id, update_data):
123
+ """Actualiza un análisis existente con manejo de errores"""
124
+ try:
125
+ query = {"_id": analysis_id}
126
+ update = {"$set": update_data}
127
+ return update_document(COLLECTION_NAME, query, update) > 0
128
+ except PyMongoError as e:
129
+ logger.error(f"Error al actualizar: {str(e)}")
130
+ return False
 
 
 
 
 
 
131
 
132
+ def delete_student_semantic_live_analysis(analysis_id):
133
+ """Elimina un análisis con manejo de errores"""
134
+ try:
135
+ query = {"_id": analysis_id}
136
+ return delete_document(COLLECTION_NAME, query) > 0
137
+ except PyMongoError as e:
138
+ logger.error(f"Error al eliminar: {str(e)}")
139
+ return False
140
 
141
+ def get_student_semantic_live_data(username):
142
+ """
143
+ Obtiene todos los análisis semánticos en vivo de un estudiante.
144
+ Versión corregida que usa la función _live.
145
+ """
146
+ try:
147
+ analyses = get_student_semantic_live_analysis(username, limit=None)
148
+
149
+ formatted_analyses = []
150
+ for analysis in analyses:
151
+ formatted_analysis = {
152
+ 'timestamp': analysis.get('timestamp'),
153
+ 'text': analysis.get('text', ''),
154
+ 'key_concepts': analysis.get('key_concepts', []),
155
+ 'concept_graph': analysis.get('concept_graph')
156
+ }
157
+ formatted_analyses.append(formatted_analysis)
158
+
159
+ return {
160
+ 'username': username,
161
+ 'entries': formatted_analyses,
162
+ 'count': len(formatted_analyses),
163
+ 'status': 'success'
164
+ }
165
+
166
  except Exception as e:
167
+ logger.error(f"Error al obtener datos: {str(e)}")
168
+ return {
169
+ 'username': username,
170
+ 'entries': [],
171
+ 'count': 0,
172
+ 'status': 'error',
173
+ 'error': str(e)
174
+ }
175
 
176
  __all__ = [
177
  'store_student_semantic_live_result',
178
+ 'get_student_semantic_live_analysis',
179
+ 'update_student_semantic_live_analysis',
180
+ 'delete_student_semantic_live_analysis',
181
+ 'get_student_semantic_live_data'
182
  ]