Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
API filter Identitas Hierarki memungkinkan visual yang menggunakan Pemetaan Matriks DataView untuk memfilter data pada beberapa bidang pada satu waktu berdasarkan titik data yang menggunakan struktur hierarki.
API ini berguna dalam skenario berikut:
- Memfilter hierarki berdasarkan titik data
- Visual kustom yang menggunakan model semantik dengan grup pada kunci
Catatan
API filter Identitas Hierarki tersedia dari API versi 5.9.0
Antarmuka filter ditunjukkan dalam kode berikut:
interface IHierarchyIdentityFilter<IdentityType> extends IFilter {
target: IHierarchyIdentityFilterTarget;
hierarchyData: IHierarchyIdentityFilterNode<IdentityType>[];
}
$schema:
https://powerbi.com/product/schema#hierarchyIdentity(diwariskan dari IFilter)filterType: FilterType.HierarchyIdentity (diwarisi dari IFilter)
target: Array kolom yang relevan dalam kueri. Saat ini hanya satu peran yang didukung; oleh karena itu, target tidak diperlukan dan harus kosong.
hierarchyData: item yang dipilih dan tidak dipilih dalam pohon hierarki di mana masing-masing
IHierarchyIdentityFilterNode<IdentityType>mewakili satu pilihan nilai.
type IHierarchyIdentityFilterTarget = IQueryNameTarget[]
interface IQueryNameTarget {
queryName: string;
}
- queryName: nama kueri kolom sumber dalam kueri. Itu berasal dari
DataViewMetadataColumn
interface IHierarchyIdentityFilterNode<IdentityType> {
identity: IdentityType;
children?: IHierarchyIdentityFilterNode<IdentityType>[];
operator: HierarchyFilterNodeOperators;
}
identity: Identitas node di DataView. Harus
IdentityTypeCustomVisualOpaqueIdentitychildren: Daftar anak simpul yang relevan dengan pilihan saat ini
operator: Operator untuk objek tunggal di pohon. Operator dapat menjadi salah satu dari tiga opsi berikut:
type HierarchyFilterNodeOperators = "Selected" | "NotSelected" | "Inherited";Dipilih: nilai dipilih secara eksplisit.
NotSelected: nilai secara eksplisit tidak dipilih.
Diwariskan: pemilihan nilai sesuai dengan nilai induk dalam hierarki, atau default jika itu adalah nilai akar.
Ingatlah aturan berikut saat menentukan filter identitas hierarki Anda:
- Ambil identitas dari DataView.
- Setiap jalur identitas harus menjadi jalur yang valid di DataView.
- Setiap daun harus memiliki operator Dipilih atau Tidak Dipilih.
- Untuk membandingkan
ICustomVisualsOpaqueUtils.compareCustomVisualOpaqueIdentitiesidentitas, gunakan fungsi . - Identitas mungkin mengubah perubahan bidang berikut (misalnya, menambahkan atau menghapus bidang). Power BI menetapkan identitas yang diperbarui ke filter.hierarchyData yang sudah ada.
Cara menggunakan API filter identitas Hierarki
Kode berikut adalah contoh cara menggunakan API filter identitas hierarki dalam visual kustom:
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();
Untuk menerapkan filter, gunakan applyJsonFilter panggilan API:
this.host.applyJsonFilter(filter, "general", "filter", action);
Untuk memulihkan filter JSON aktif, gunakan properti yang jsonFilters ditemukan di "VisualUpdateOptions":
export interface VisualUpdateOptions extends extensibility.VisualUpdateOptions {
//...
jsonFilters?: IFilter[];
}
Validasi bidang terkait hierarki (opsional)
HierarchyIdnetity Filter hanya didukung untuk bidang terkait hierarkis. Secara default, Power BI tidak memvalidasi apakah bidang terkait secara hierarkis.
Untuk mengaktifkan validasi terkait hierarkis, tambahkan properti 'areHierarchicallyRelated' ke kondisi peran yang relevan dalam file capabilities.json:
"dataViewMappings": [
{
"conditions": [
{
"Rows": {
"min": 1,
"areHierarchicallyRelated": true <------ NEW ------>
},
"Value": {
"min": 0
}
}
],
...
}
]
Bidang terkait secara hierarkis jika kondisi berikut terpenuhi:
Tidak termasuk hubungan tepi banyak untuk banyak kardinalitas, atau
ConceptualNavigationBehavior.Weak.Semua bidang dalam filter ada di jalur.
Setiap hubungan di jalur memiliki arah atau dua arah yang sama.
Arah hubungan cocok dengan kardinalitas untuk satu hingga banyak atau dua arah.
Contoh hubungan hierarki
Misalnya, mengingat hubungan entitas berikut:
- A, B terkait hierarkis: true
- B, C terkait hierarkis: true
- A, B, C terkait hierarkis: true
- A, C, E terkait hierarkis: true (A --> E --> C)
- A, B, E terkait hierarkis: true (B --> A --> E)
- A, B, C, E terkait hierarkis: true (B --> A --> E --> C)
- A, B, C, D terkait hierarkis: false (aturan yang dilanggar #3)
- C, D terkait hierarkis: true
- B, C, D terkait hierarkis: false (aturan yang dilanggar #3)
- A, C, D, E terkait hierarkis: false (aturan yang dilanggar #3)
Catatan
Ketika validasi ini diaktifkan, dan bidang tidak terkait secara hierarkis, visual tidak akan dirender, dan pesan kesalahan akan ditampilkan:
Ketika validasi ini dinonaktifkan, dan visual filter menerapkan filter yang berisi simpul yang terkait dengan bidang terkait non-hierarkis, visual lain mungkin tidak dirender dengan benar saat pengukuran sedang digunakan:
Contoh kode untuk memperbarui pohon data hierarki setelah pilihan baru
Kode berikut menunjukkan cara memperbarui hierarchyData pohon setelah baru memilih:
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();
}
Pertimbangan dan batasan
Filter ini hanya didukung untuk pemetaan dataView matriks.
Visual hanya boleh berisi satu peran data pengelompokan.
Visual yang menggunakan jenis filter identitas Hierarki hanya boleh menerapkan satu filter jenis ini.