Naar inhoud
Pivotick
Main Navigation Startpagina
Aan de slag
Configuratie
Gegenereerde API-documentatie
GalerijProjectenProbeer het uit!

Nederlands

English
简体中文
Français
Deutsch
Português
日本語
العربية
Español

Nederlands

English
简体中文
Français
Deutsch
Português
日本語
العربية
Español

Weergave

Sidebar Navigation

Aan de slag

Projecten met Pivotick

Configuratie

Callbacks

Verbindingslagen

Vereenvoudigen

Indeling

Weergave

Simulatie

Interface aanpassen

Zijbalk

Tooltip

Contextmenu

Filters

Legenda

Gegevenstabel

Interface vormgeven

Interface vertalen

Plug-ins

Pivotick-API

Pivots en verrijking

Pivotresultaten opslaan

Ongedaan maken en geschiedenis

Beveiliging

API-documentatie

Galerij

Basis

Knopen vormgeven

Verbindingen vormgeven

Indelingen

Gebeurtenissen en callbacks

Interface aanpassen

Bewerken en maken

Notities en annotaties

Filteren, zoeken en hiërarchie

Programmatische besturing

Thema's en prestaties

Pivots en verrijking

Uitgelichte voorbeelden

Filter-/query-engine ​

Echte datasets zijn te groot om allemaal in één keer weer te geven. graph.queryEngine filtert de grafiek op knooppuntattributen: setFilter(key, spec) bewaart knooppunten waarvan data[key] overeenkomt — een exacte waarde, een lijst of een numeriek { min, max } bereik — en meerdere filters EN samen. resetFilters() wist ze.

Afgezien van de attribuutregels verbergt excludeNode(id) één knooppunt met de hand; includeNode(id) brengt het terug en clearNodeExclusions() herstelt elk handmatig verborgen knooppunt.

De onderstaande knoppen sturen de motor rechtstreeks aan. Dezelfde filtering is beschikbaar zonder code: in volledige modus draagt de header een paneel Grafiekfilters (het trechterpictogram of druk op Shift+K). Code en paneel blijven gesynchroniseerd: filter van a knop, open het paneel en de bedieningselementen weerspiegelen al het actieve filter, terwijl verborgen knooppunten verschijnen in de lijst Verborgen knooppunten.

Deze kaart verklaart de facetten ervan (UI.filter.facets), dus het paneel bevat precies de zes onderstaande bedieningselementen met de gegeven labels en widgets - inclusief twee die helemaal geen knooppuntgegevenssleutels zijn. Laat facets weg en het paneel leidt in plaats daarvan a af controle per datasleutel, waarbij elke widget wordt afgeleid uit de gevonden waarden; zie Filteropties.

tags is array-waarde, dus als je dit filtert, wordt het lidmaatschap getest: tag = kritisch zorgt ervoor dat elk knooppunt die tag draagt. Depends on load ≥ is berekend — een accessor leest de belasting van dependencies' in plaats van die van het knooppunt, wat de reden is web-1 (de drukste dienst met 82%) valt eruit, terwijl de stillere db-1 overleeft.

Stapel ze: type = api en vervolgens load ≥ 70 laat alleen de ene drukke API over.

js
// Distinct values of a key across the graph, flattening array-valued data — so a
// select's options follow the data without the facet set itself churning.
function distinct(graph, key) {
    const values = new Set()
    for (const node of graph.getNodes()) {
        const value = node.getData()[key]
        if (Array.isArray(value)) value.forEach((entry) => values.add(entry))
        else if (value !== null && value !== undefined) values.add(String(value))
    }
    return [...values].sort().map((value) => ({ label: value, value }))
}

// Declaring facets replaces the panel's data-scanning: exactly these fields, in
// this order, with these labels and widgets. Omit `UI.filter.facets` entirely and
// the panel derives a control per data key instead (the zero-config default).
const facets = [
    { key: 'type', label: 'Service type', type: 'multiselect', options: (g) => distinct(g, 'type') },
    { key: 'zone', label: 'Region', type: 'select', options: (g) => distinct(g, 'zone') },
    { key: 'load', label: 'Load (%)', type: 'numberRange' },

    // Array-valued data: a filter tests membership, so picking `critical` matches
    // every node carrying that tag — one control, no flattened shadow data key.
    { key: 'tags', label: 'Tag', type: 'multiselect', options: (g) => distinct(g, 'tags') },

    // Computed: `accessor` reads whatever you like, here the *dependencies'* load
    // rather than the node's own data — "which services depend on a busy one?".
    {
        key: 'dep_load', label: 'Depends on load ≥', type: 'numberRange',
        accessor: (node) => node.getEdgesOut().map((edge) => edge.to.getData().load)
    },

    // Full control: decide membership yourself.
    {
        key: 'name', label: 'Name matches', type: 'regex',
        predicate: (node, value) => new RegExp(value, 'i').test(node.id)
    }
]
js
// Everything the built-in panel does is available programmatically on
// graph.queryEngine. setFilter(key, spec) keys off the facet's key and applies at
// once; call it for several keys and the filters AND together.
function filterByType(graph, type) {
    graph.queryEngine.setFilter('type', { value: type, matchMode: 'exact' })
}

// A numeric spec takes a { min, max } range (either bound may be omitted).
function filterByLoad(graph, min) {
    graph.queryEngine.setFilter('load', { value: { min, max: undefined } })
}

// Array-valued data matches by membership: this keeps every node tagged 'critical'.
// Pass an array for any-of, or add matchMode: 'all' to require every tag.
function filterByTag(graph, tag) {
    graph.queryEngine.setFilter('tags', { value: tag })
}

// The computed facet: the node's own load is irrelevant, its dependencies' isn't.
function filterByDependencyLoad(graph, min) {
    graph.queryEngine.setFilter('dep_load', { value: { min, max: undefined } })
}

// resetFilters clears every active filter and restores the full graph.
function clearFilters(graph) {
    graph.queryEngine.resetFilters()
}

// Attribute rules aside, excludeNode(id) hides a single node by hand. It's tracked
// separately from setFilter rules and listed in the panel's "Hidden nodes" section;
// includeNode(id) restores one, clearNodeExclusions() restores them all.
function excludeNode(graph, id) {
    graph.queryEngine.excludeNode(id)
}

function clearExclusions(graph) {
    graph.queryEngine.clearNodeExclusions()
}
js
const options = {
    // Full mode ships the built-in Graph Filters panel (open it from the header's
    // funnel, or Shift+K). Its form is generated from the facets declared below;
    // without `filter.facets` it auto-discovers your node attributes instead.
    UI: {
        mode: 'full',
        // Off: `full` mode brings a minimap and the data dock, and this card is about
        // neither (see the Minimap and Data table cards for those).
        minimap: false,
        table: false,
        filter: { facets }
    },
    render: {
        nodeTypeAccessor: (node) => node.getData().type,
        nodeStyleMap: {
            web: { color: palette.web },
            api: { color: palette.api },
            db: { color: palette.db }
        }
    }
}
js
// A small service-dependency graph. Each node carries categorical fields (type,
// zone), a numeric one (load) and an array-valued one (tags) — exactly the kind of
// data the filter engine and its built-in UI slice on. Colouring by type is purely
// so the filtering reads clearly (see the Node styling cards for the technique).
const palette = { web: '#0072B2', api: '#E69F00', db: '#009E73' }

const data = {
    nodes: [
        { id: 'web-1', data: { type: 'web', zone: 'eu', load: 82, tags: ['public', 'critical'] } },
        { id: 'web-2', data: { type: 'web', zone: 'us', load: 45, tags: ['public'] } },
        { id: 'api-1', data: { type: 'api', zone: 'eu', load: 68, tags: ['internal'] } },
        { id: 'api-2', data: { type: 'api', zone: 'us', load: 91, tags: ['internal', 'critical'] } },
        { id: 'api-3', data: { type: 'api', zone: 'eu', load: 30, tags: [] } },
        { id: 'db-1', data: { type: 'db', zone: 'eu', load: 55, tags: ['critical'] } },
        { id: 'db-2', data: { type: 'db', zone: 'us', load: 74, tags: ['critical'] } }
    ],
    edges: [
        { from: 'web-1', to: 'api-1' },
        { from: 'web-1', to: 'api-3' },
        { from: 'web-2', to: 'api-2' },
        { from: 'api-1', to: 'db-1' },
        { from: 'api-2', to: 'db-2' },
        { from: 'api-3', to: 'db-1' },
        { from: 'db-1', to: 'db-2' }
    ]
}
Pager
Volgende paginaAan de slag