Crear reglas de validación contextuales
Este procedimiento muestra cómo crear reglas de validación que comprueben condiciones entre varios objetos mediante el contexto de validación. Estas reglas son solo ilustrativas y no reflejan necesariamente requisitos técnicos estrictos de Metric Views ni de Semantic Bridge.
Note
Estas guías prácticas están dirigidas a Tabular Editor 3.26.2 y versiones posteriores. Las versiones anteriores no admiten las características de Metric View v1.1 que se muestran aquí.
Cuándo usar reglas contextuales
Use reglas contextuales cuando necesite:
- Comprueba que no se reutilice un mismo nombre entre distintos tipos de objeto
- Acceder a información sobre objetos validados previamente
Note
El proceso de validación revisa cada objeto de Metric View en orden (primero los joins, luego los campos y después las medidas), por lo que el contexto solo incluye los elementos que ya se han validado durante la validación.
El método MakeValidationRule
El método genérico MakeValidationRule<T> proporciona acceso al contexto de validación:
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>( // o Field, Join, View
"rule_name",
"category",
// devuelve un IEnumerable<DiagnosticMessage>;
// una colección vacía significa que el objeto ha superado la validación
(obj, context) => []
);
El parámetro context proporciona:
context.FieldNames- nombres de los campos ya validadoscontext.MeasureNames- nombres de las medidas ya validadascontext.JoinNames- nombres de los joins ya validadoscontext.MakeError(code, message, object)- crea un diagnóstico de error para el objeto especificadocontext.MakeWarning(code, message, object)- crea un diagnóstico de advertencia para el objeto especificado
Como creas el mensaje de diagnóstico en el cuerpo de la función de validación, puedes incluir en el mensaje detalles sobre el objeto actual que se está validando.
Directiva using para los tipos de Metric View
Agrega esta directiva using para hacer referencia a los tipos de Metric View:
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
Regla: el nombre de una medida de Metric View no debe coincidir con el de un campo de Metric View
Los campos se validan antes que las medidas, así que, cuando se comprueba una medida, context.FieldNames ya contiene todos los nombres de los campos.
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
var measureNameRule = SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_field_name",
"naming",
(measure, context) =>
context.FieldNames.Contains(measure.Name)
? [context.MakeError(
"measure_field_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un campo",
measure)]
: []
);
Regla: el nombre de una medida de Metric View no debe coincidir con el de un join de Metric View
Los joins se validan primero, por lo que context.JoinNames contiene todos los nombres de los joins cuando se comprueban las medidas.
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
var measureNotJoinRule = SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_join_name",
"naming",
(measure, context) =>
context.JoinNames.Contains(measure.Name)
? [context.MakeError(
"measure_join_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un join",
measure)]
: []
);
Por qué es mejor separar las reglas
Fíjate en que creamos dos reglas separadas en lugar de una regla combinada. Este es el enfoque recomendado porque:
- Mensajes de error más claros: Cada regla genera un mensaje específico y útil
- Mantenimiento más sencillo: Las reglas se pueden agregar, quitar o modificar de forma independiente
- Lógica más sencilla: Cada regla comprueba exactamente una condición
- Mejor categorización: Las reglas se pueden agrupar y filtrar según su finalidad
Ejemplo completo
Este Metric View tiene conflictos de nombres que activarán ambas reglas contextuales:
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
// Crear una Metric View con nombres reutilizados entre tipos de objeto
SemanticBridge.MetricView.Deserialize("""
version: 1.1
source: sales.fact.orders
joins:
- name: customer
source: sales.dim.customer
on: source.customer_id = customer.customer_id
cardinality: many_to_one
fields:
# 'revenue' también se usa como nombre de medida más abajo
- name: revenue
expr: source.revenue
- name: quantity
expr: source.quantity
measures:
# infracción de measureNameRule: mismo nombre que el campo 'revenue'
- name: revenue
expr: SUM(source.revenue)
# infracción de measureNotJoinRule: mismo nombre que el join 'customer'
- name: customer
expr: COUNT(DISTINCT source.customer_id)
# esta medida está bien
- name: order_count
expr: COUNT(source.order_id)
""");
var measureNameRule = SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_field_name",
"naming",
(measure, context) =>
context.FieldNames.Contains(measure.Name)
? [context.MakeError(
"measure_field_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un campo",
measure)]
: []
);
var measureNotJoinRule = SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_join_name",
"naming",
(measure, context) =>
context.JoinNames.Contains(measure.Name)
? [context.MakeError(
"measure_join_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un join",
measure)]
: []
);
// Ejecutar la validación con ambas reglas
var diagnostics = SemanticBridge.MetricView.Validate([
measureNameRule,
measureNotJoinRule
]).ToList();
// Mostrar resultados
var sb = new System.Text.StringBuilder();
sb.AppendLine("RESULTADOS DE VALIDACIÓN CONTEXTUAL");
sb.AppendLine("-----------------------------");
sb.AppendLine("");
sb.AppendLine($"Se encontraron {diagnostics.Count} problema(s):");
sb.AppendLine("");
foreach (var diag in diagnostics)
{
sb.AppendLine($"[{diag.Severity}] {diag.Message}");
}
Output(sb.ToString());
Salida:
RESULTADOS DE VALIDACIÓN CONTEXTUAL
-----------------------------
Se encontraron 2 problema(s):
[Error] La medida 'revenue' tiene el mismo nombre que un campo
[Error] La medida 'customer' tiene el mismo nombre que un join
Combinar con las reglas predeterminadas
Puedes ejecutar reglas contextuales junto con las reglas de validación predeterminadas llamando a Validate dos veces:
using MetricView = TabularEditor.SemanticBridge.Platforms.Databricks.MetricView;
var customRules = new[] {
SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_field_name",
"naming",
(measure, context) =>
context.FieldNames.Contains(measure.Name)
? [context.MakeError(
"measure_field_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un campo",
measure)]
: []),
SemanticBridge.MetricView.MakeValidationRule<MetricView.Measure>(
"measure_not_join_name",
"naming",
(measure, context) =>
context.JoinNames.Contains(measure.Name)
? [context.MakeError(
"measure_join_name_collision",
$"La medida '{measure.Name}' tiene el mismo nombre que un join",
measure)]
: [])
};
// Ejecuta primero las reglas predeterminadas
var defaultDiagnostics = SemanticBridge.MetricView.Validate().ToList();
// Después ejecuta las reglas personalizadas
var customDiagnostics = SemanticBridge.MetricView.Validate(customRules).ToList();
var sb = new System.Text.StringBuilder();
sb.AppendLine($"Problemas de las reglas predeterminadas: {defaultDiagnostics.Count}");
sb.AppendLine($"Problemas de las reglas personalizadas: {customDiagnostics.Count}");
Output(sb.ToString());
Salida
Problemas de las reglas predeterminadas: 0
Problemas de las reglas personalizadas: 2