Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber másEste explorador ya no se admite.
Actualice a Microsoft Edge para aprovechar las características y actualizaciones de seguridad más recientes, y disponer de soporte técnico.
La API de filtro de identidad de jerarquía permite a los objetos visuales que usan la asignación de DataView de matriz para filtrar datos en varios campos a la vez en función de los puntos de datos que usan una estructura de jerarquía.
Esta API es útil en los escenarios siguientes:
Nota
La API de filtro de identidad de jerarquía está disponible en la versión 5.9.0 de la API
En el código siguiente se muestra la interfaz de filtro:
interface IHierarchyIdentityFilter<IdentityType> extends IFilter {
target: IHierarchyIdentityFilterTarget;
hierarchyData: IHierarchyIdentityFilterNode<IdentityType>[];
}
$schema: https://powerbi.com/product/schema#hierarchyIdentity
(heredado de IFilter)
filterType: FilterType.HierarchyIdentity (heredado de IFilter)
target: matriz de columnas pertinentes en la consulta. Actualmente solo se admite un solo rol; por lo tanto, el destino no es necesario y debe estar vacío.
hierarchyData: los elementos seleccionados y no seleccionados en un árbol de jerarquía donde cada IHierarchyIdentityFilterNode<IdentityType>
representa una selección de valor único.
type IHierarchyIdentityFilterTarget = IQueryNameTarget[]
interface IQueryNameTarget {
queryName: string;
}
DataViewMetadataColumn
interface IHierarchyIdentityFilterNode<IdentityType> {
identity: IdentityType;
children?: IHierarchyIdentityFilterNode<IdentityType>[];
operator: HierarchyFilterNodeOperators;
}
identity: la identidad del nodo en DataView. IdentityType
debe ser CustomVisualOpaqueIdentity
children: lista de elementos secundarios de nodo relevantes para la selección actual
operator: operador para objetos únicos en el árbol. El operador puede ser una de las tres opciones siguientes:
type HierarchyFilterNodeOperators = "Selected" | "NotSelected" | "Inherited";
Selected: el valor se selecciona explícitamente.
NotSelected: el valor no está seleccionado explícitamente.
Inherited: la selección de valores se basa en el valor primario de la jerarquía o el valor predeterminado si es el valor raíz.
Tenga en cuenta las siguientes reglas al definir el filtro de identidad de la jerarquía:
ICustomVisualsOpaqueUtils.compareCustomVisualOpaqueIdentities
.El código siguiente es un ejemplo de cómo usar la API de filtro de identidad de jerarquía en un objeto visual personalizado:
import { IHierarchyIdentityFilterTarget, IHierarchyIdentityFilterNode, HierarchyIdentityFilter } from "powerbi-models"
const target: IHierarchyIdentityFilterTarget = [];
const hierarchyData: IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity>[] = [
{
identity: {...},
operator: "Selected",
children: [
{
identity: {...},
operator: "NotSelected"
}
]
},
{
identity: {...},
operator: "Inherited",
children: [
{
identity: {...},
operator: "Selected"
}
]
}
];
const filter = new HierarchyIdentityFilter(target, hierarchyData).toJSON();
Para aplicar el filtro, use la llamada API applyJsonFilter
:
this.host.applyJsonFilter(filter, "general", "filter", action);
Para restaurar el filtro JSON activo, use la propiedad jsonFilters
que se encuentra en "VisualUpdateOptions":
export interface VisualUpdateOptions extends extensibility.VisualUpdateOptions {
//...
jsonFilters?: IFilter[];
}
El filtro HierarchyIdnetity
solo se admite para campos relacionados jerárquicamente. De forma predeterminada, Power BI no valida si los campos están relacionados jerárquicamente.
Para activar la validación relacionada jerárquicamente, agregue la propiedad "areHierarchicallyRelated" a la condición de rol pertinente en el archivo de capabilities.json:
"dataViewMappings": [
{
"conditions": [
{
"Rows": {
"min": 1,
"areHierarchicallyRelated": true <------ NEW ------>
},
"Value": {
"min": 0
}
}
],
...
}
]
Los campos están relacionados jerárquicamente si se cumplen las condiciones siguientes:
Ningún borde de relación incluido es cardinalidad de muchos a muchos, ni ConceptualNavigationBehavior.Weak
.
Todos los campos del filtro existen en la ruta de acceso.
Cada relación de la ruta de acceso tiene la misma dirección o bidireccional.
La dirección de la relación coincide con la cardinalidad de uno a varios o bidireccional.
Por ejemplo, dada la siguiente relación de entidad:
Nota
Cuando estas validaciones están habilitadas y los campos no están relacionados jerárquicamente, el objeto visual no se representará y se mostrará un mensaje de error:
Cuando estas validaciones están deshabilitadas y el objeto visual de filtro aplica un filtro que contiene nodos relacionados con campos no jerárquicos, es posible que otros objetos visuales no se representen correctamente cuando se usen medidas:
El código siguiente muestra cómo actualizar el árbol hierarchyData
después de una nueva selección:
type CompareIdentitiesFunc = (id1: CustomVisualOpaqueIdentity, id2: CustomVisualOpaqueIdentity) => boolean;
/**
* Updates the filter tree following a new node selection.
* Prunes irrelevant branches after node insertion/removal if necessary.
* @param path Identities path to the selected node.
* @param treeNodes Array of IHierarchyIdentityFilterNode representing a valid filter tree.
* @param compareIdentities Compare function for CustomVisualOpaqueIdentity to determine equality. Pass the ICustomVisualsOpaqueUtils.compareCustomVisualOpaqueIdentities function.
* @returns A valid filter tree after the update
*/
function updateFilterTreeOnNodeSelection(
path: CustomVisualOpaqueIdentity[],
treeNodes: IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity>[],
compareIdentities: CompareIdentitiesFunc
): IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity>[] {
if (!path) return treeNodes;
const root: IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity> = {
identity: null,
children: treeNodes || [],
operator: 'Inherited',
};
let currentNodesLevel = root.children;
let isClosestSelectedParentSelected = root.operator === 'Selected';
let parents: { node: IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity>, index: number }[] = [{ node: root, index: -1 }];
let shouldFixTree = false;
path.forEach((identity, level) => {
const index = currentNodesLevel.findIndex((node) => compareIdentities(node.identity, identity));
const isLastNodeInPath = level === path.length - 1
if (index === -1) {
const newNode: IHierarchyIdentityFilterNode<CustomVisualOpaqueIdentity> = {
identity,
children: [],
operator: isLastNodeInPath ? (isClosestSelectedParentSelected ? 'NotSelected' : 'Selected') : 'Inherited',
};
currentNodesLevel.push(newNode);
currentNodesLevel = newNode.children;
if (newNode.operator !== 'Inherited') {
isClosestSelectedParentSelected = newNode.operator === 'Selected';
}
} else {
const currentNode = currentNodesLevel[index];
if (isLastNodeInPath) {
const partial = currentNode.children && currentNode.children.length;
if (partial) {
/**
* The selected node has subtree.
* Therefore, selecting this node should lead to one of the following scenarios:
* 1. The node should have Selected operator and its subtree should be pruned.
* 2. The node and its subtree should be pruned form the tree and the tree should be fixed.
*/
// The subtree should be always pruned.
currentNode.children = [];
if (currentNode.operator === 'NotSelected' || (currentNode.operator === 'Inherited' && isClosestSelectedParentSelected )) {
/**
* 1. The selected node has NotSelected operator.
* 2. The selected node has Inherited operator, and its parent has Slected operator.
* In both cases the node should be pruned from the tree and the tree shoud be fixed.
*/
currentNode.operator = 'Inherited'; // to ensure it will be pruned
parents.push({ node: currentNode, index });
shouldFixTree = true;
} else {
/**
* 1. The selected node has Selected operator.
* 2. The selected node has Inherited operator, but its parent doesn't have Selected operator.
* In both cases the node should stay with Selected operator pruned from the tree and the tree should be fixed.
* Note that, node with Selected oprator and parent with Selector operator is not valid state.
*/
currentNode.operator = 'Selected';
}
} else {
// Leaf node. The node should be pruned from the tree and the tree should be fixed.
currentNode.operator = 'Inherited'; // to ensure it will be pruned
parents.push({ node: currentNode, index });
shouldFixTree = true;
}
} else {
// If it's not the last noded in path we just continue traversing the tree
currentNode.children = currentNode.children || [];
currentNodesLevel = currentNode.children
if (currentNode.operator !== 'Inherited') {
isClosestSelectedParentSelected = currentNode.operator === 'Selected';
// We only care about the closet parent with Selected/NotSelected operator and its children
parents = [];
}
parents.push({ node: currentNode, index });
}
}
});
// Prune brnaches with Inherited leaf
if (shouldFixTree) {
for (let i = parents.length - 1; i >= 1; i--) {
// Normalize to empty array
parents[i].node.children = parents[i].node.children || [];
if (!parents[i].node.children.length && (parents[i].node.operator === 'Inherited')) {
// Remove the node from its parent children array
removeElement(parents[i - 1].node.children, parents[i].index);
} else {
// Node has children or Selected/NotSelected operator
break;
}
}
}
return root.children;
}
/**
* Removes an element from the array without preserving order.
* @param arr - The array from which to remove the element.
* @param index - The index of the element to be removed.
*/
function removeElement(arr: any[], index: number): void {
if (!arr || !arr.length || index < 0 || index >= arr.length) return;
arr[index] = arr[arr.length - 1];
arr.pop();
}
Este filtro solo se admite para la asignación de dataView de matriz.
El objeto visual debe contener solo un rol de datos de agrupación.
Un objeto visual que use el tipo de filtro de identidad de jerarquía solo debe aplicar un solo filtro de este tipo.
Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber más