Draaipunten en verrijking
Een pivot is een uitvoerbare verrijking: "laat me zien wat de bron hierover nog meer heeft". Jij declareer het, de bibliotheek voert het uit, ensceneert de resultaten voor triage en legt ze vast in het grafiek met de herkomst van elk element zodra de analist dat zegt.
Het probleem dat het oplost is dat het interessante knooppunt meestal te veel verbindingen heeft. EEN Eén enkele indicator kan gerelateerd zijn aan duizenden andere. Een pivot is dus twee oproepen in plaats van één: een goedkoop telefoontje dat zegt wat er is, en een duur telefoontje dat alleen maar doorgaat een getal waar de analist mee instemde.
Woordenschat, overal hieronder consistent gebruikt
- pivot: de uitvoerbare verrijking
- provider: de twee functies die u levert
- candidates: resultaten opgehaald, nog niet in de grafiek
- ingest: het vastleggen van de gekozen kandidaten in de grafiek
- reject: een expliciet ontslag, onthouden voor de sessie
- source: de herkomsttag geschreven op alles waar een draaipunt terechtkomt
- save: een opgenomen resultaat terugschrijven out, naar het systeem waar het vandaan kwam
- unsaved: op het canvas, nog niet teruggeschreven — een exacte telling, geen schatting
summarize → fetch → triage → ingest → save
"2,143" the 210 the 12 on canvas in the source systemAlleen fetch is vereist. Al het andere op die lijn is een stap waarvoor u zich aanmeldt.
Zie het werken: Draaien en verrijken voor de vernauwing van de stroom, en Weigeren en opnieuw proberen voor triage en faaltoestanden.
Een gebruiken is wat een analist doet, in volgorde, en wat elke stap kost backend. Alles vanaf Eén registreren is de referentie voor degene die er een aansluit, en Wat uw bron te bieden heeft is hetzelfde contract, gelezen vanaf de kant van de dienst.
Eén gebruiken
1 · Ga naar de draaimodus. Druk op P of klik op de Pivot gleuf op de linkerrail. Het slot bestaat alleen als er minimaal één draaipunt is geregistreerd. Er is van niemand iets gevraagd backend nog niet, en het selecteren van knooppunten terwijl de modus gesloten is, vraagt ook niets. Box-selectie vijftig knooppunten om ze te slepen mogen geen vijftig telquery's afvuren.
2 · Kies een oorsprong. De oorsprong is de knooppuntenset waar de vraag over gaat. Kies oorsprong is het rustgereedschap, dus een simpele klik zet het vast. Lasso-oorsprong tekent rond verschillende. Wat dan ook al geselecteerd was toen u de modus binnenging, wordt de oorsprong, en Clear maakt deze leeg. Een lege oorsprong heeft nog steeds toepassingen: draaipunten die als origin: 'none' zijn aangegeven, zijn van toepassing als er niets wordt geplukt.
3 · Lees wat van toepassing is. Het betreden van de modus is de intentie die summarize wordt uitgevoerd, eenmaal per toepasselijk draaipunt, gebundeld in een enkele oproep voor een oorsprong met meerdere knooppunten. Bij elke invoer staat wat de beweringen van de provider zijn beschikbaar, geschreven als ~2,143. De tilde markeert een nummer van de aanbieder beweerde in plaats van een die de bibliotheek telde. Een draaipunt zonder summarize toont een kale Uitvoeren in plaats daarvan. Als er niets van toepassing is, zegt het panel dat in plaats van een lege lijst te tonen.
4 · Smal totdat de poort opengaat. Een draaipunt dat maxCandidates aangeeft, behoudt Fetch buiten bereik terwijl de telling dit overschrijdt, en vermeldt het aantal, de limiet en de weg vooruit. Als u een beperkend besturingselement aanvinkt, wordt summarize opnieuw gevraagd met die keuze, dus 2.143 wordt 210 en Fetch worden vanzelf ingeschakeld. Duidelijke vernauwing begint opnieuw. Ernaast, Ophalen & ingest plaatst elk resultaat zonder beoordeling in de grafiek. Het wordt alleen aangeboden waar het draaipunt aanwezig is links autoIngest uitgeschakeld.
5 · Triage wat er terugkwam. De resultaten raken de grafiek niet. Ze openen het tabblad Beoordeling in het onderste dock, één venster per provider die u hebt uitgevoerd, vermeld aan de zijkant. Klik ergens op een rij om deze te markeren, houd Shift ingedrukt en klik om de markering over een bereik te verplaatsen, en Selecteer alles wat overeenkomt respecteert het huidige filter; Zoek rijen… filters (regex optioneel) en sorteer de kolommen. Weiger geselecteerde en Weiger alle resterende verwijder rijen expliciet en worden onthouden voor de sessie, terwijl de × slechts een venster sluit en niets afwijst. Opnieuw uitvoeren vraagt opnieuw met dezelfde vernauwing. Aan de voet van de strip laat Sluiten mislukt elke ophaalactie vallen die heeft niets teruggebracht en Alles sluiten maakt de wachtrij leeg; noch wijst ook iets af. Kandidaten zijn niet de grafiek heeft de rest ervan.
6 · Opnemen, en ongedaan maken als het verkeerd was. Ingest geselecteerd (12) legt precies die vast twaalf, geplaatst rond het knooppunt waaruit u draaide en getagd met het draaipunt als hun bron. Ingest all 213 ernaast slaat de markering over en legt alles vast wat de provider nog steeds doet aanbod, waar de tabel ook op wordt gefilterd. Op de toast staat Ingested 12 nodes, 14 edges. Het terugnemen is de knop voor ongedaan maken in de bovenste balk, die daar permanent is in plaats van voor zolang een toast duurt, en de hele reeks omkeert – de randen en alle kinderen die ermee zijn samengevoegd inbegrepen.
7 · Bewaar het terug, als het draaipunt dat kan. Ingest plaatst de twaalf op het canvas; dat is niet het geval schrijf ze waar dan ook. De voet van het Pivot-paneel geeft aan hoeveel elementen deze sessie heeft ingetrokken en niet teruggeschreven, en Opslaan schrijft ze. Een draaipunt dat geen save aangeeft draagt nooit bij aan dat aantal — zie Pivotresultaten opslaan.
Een inname die niets overlaat om over te beslissen, sluit het venster en de strip gaat door naar de volgende aanbieder wacht. Restjes houden het open, en dat geldt ook voor een herhaling die erin wacht. Een keer de laatste Als het venster naar beneden gaat, vouwt een dock dat de recensie heeft geopend terug naar de plek waar het was, zodat een draaipunt de lay-out verlaat het gevonden.
Het draaipunt met één klik
Stappen 2 tot en met 4 zijn bedoeld voor een vraag die de moeite waard is om eerst te lezen. De meeste zijn dat niet. Klik met de rechtermuisknop op een knooppunt, en Spil ▸ somt elke draaipunt op die erop van toepassing is, met wat elke draaipunt adverteert. Als je een rij kiest, wordt het daar en dan uitgevoerd: geen paneel, niets in te vullen. De oorsprong is de selectie wanneer het aangeklikte knooppunt erbij hoort en anders alleen dat knooppunt, dus een bulkdraaipunt is bereikbaar zonder het menu te verlaten.
Het openen van het submenu is ook wat er gevraagd wordt. Elke draai met een summarize wordt de eigen vraag van het panel gesteld, deze oorsprong met niets is kleiner geworden, en de rij heeft een tijdelijke aanduiding totdat de telling arriveert: ~2,143, adviserend zoals elk nummer waar een aanbieder mee adverteert. Een draaipunt dat niets adverteert, toont niets en loopt precies hetzelfde. De vragen verdwijnen pas als het submenu even wordt vastgehouden, dus een aanwijzer die Pivot ▸ kruist op weg naar elders vraagt niets, en wordt geannuleerd als het sluit eerst. Antwoorden worden in beide richtingen in de cache opgeslagen: een tweede blik schildert in één keer en het paneel hergebruikt wat het menu heeft geleerd. Een register dat langer is dan het menu kan scrollen bevatten, midden in de rij gesneden dus het leest als doorgaand.
Waar de resultaten naartoe gaan, hangt af van hoeveel ervan nieuw zijn op het canvas:
- Tot
pivotQuickIngestLimitnieuwe kandidaten (standaard 50) landen direct, getagd en ongedaan te maken zoals elke andere inname. - Meer dan dat open in plaats daarvan het tabblad Beoordeling, precies zoals bij een paneeluitvoering.
- Een weigering van de limiet gebeurt voordat er iets is opgehaald, dus er valt niets te beoordelen. De Het draaipaneel opent op dat draaipunt met het nummer en de vernauwing waardoor het omhoog wordt gebracht.
Er loopt een rij zonder dat er iets vernauwd is. Wanneer één pivot in werkelijkheid uit meerdere runs bestaat, kiest de analist tussen, zoals het verrijken van een object via een van zijn attributen, declareer menuChoices: de rij opent vervolgens een submenu met één rij per keuze, waarbij elke rij een eigen draaipunt heeft smaller wordend, en een laatste rij die het paneel op dat draaipunt opent. Het is synchroon en loopt elk tijdstip waarop het menu wordt geopend, zoals appliesTo. Een pet-weigering van een keuze opent het paneel op de de keuze wordt kleiner. Retourneer [] voor een gewone rij.
menuChoices: ([object]) => attributesOf(object).map((a) => ({
label: `${a.type}: ${a.value}`,
narrowing: { attribute: [a.id] },
})),Kandidaten die al op canvas staan, zijn niet nieuw en vullen nooit de limiet, dus er moet opnieuw een draai worden gemaakt grond die je hebt bedekt blijft een gebaar met één klik. Een rand tussen twee knooppunten die al op het scherm staan telt wel mee, want het is een rij waar je anders naar gevraagd zou zijn. Een spil die verklaard autoIngest heeft de vraag al beantwoord en het antwoord luidt: true landt altijd, false altijd beoordelingen. De limiet beslist alleen voor draaipunten die deze hebben verlaten uitgeschakeld, en alleen voor dit gebaar; een paneel Fetch is altijd in fases.
Totdat het antwoord bekend is, heeft de run niets opgeleverd, dus er is niets van het scherm nodig om het te zeggen het werkt. Een tabblad Review voegt zich bij de striplezing Review… van het dock terwijl het ophalen plaatsvindt naar buiten, zonder de kade uit te vouwen of een ruit naar voren te brengen; klik erop om de run te bekijken of annuleer het. Alleen een resultaat waarover moet worden beslist, komt naar voren, en een run die landt, neemt het resultaat ermee weg. De twee antwoorden waarvoor niets te beslissen is, zijn die van de kennisgever: a failed fetch zegt dit met een nieuwe poging en een resultaat boven het absolute candidateCeiling zegt het aantal en de limiet.
Drie manieren dus: de railmodus, het contextmenu van een knooppunt Pivot ▸ submenu (afwezig, nooit uitgeschakeld, als er niets van toepassing is), en, met pivotRimBadgeVisible: 'always', een velgbadge, die de modus opent met een eigen draaipunt, of, waarbij de rand één badge draagt voor allemaal, naar het knooppunt. Een badge voor een knooppunt met precies één draaipunt dat niets te beperken heeft, loopt het direct, als een menurij.
Eén registreren
Drie deuren, één register, in de volgorde waarin u ze zou pakken:
// 1. Options, at construction. Lands before the UI is built, so the rail button is
// already right on the first paint.
const graph = new Pivotick(el, data, { pivots: [correlations] })
// 2. Imperatively, at any point. Returns a disposer.
const remove = graph.pivots.register(correlations)
// 3. From a plugin's install, beside addPanel / addDockTab / addRailMode.
ctx.addPivot(correlations)graph.pivots is zowel het register als de runtime. for(), run(), undo(), invalidate() en het kandidaat-model hangen er allemaal aan vast.
Een complete aanbieder
Alles wat een werkende spil nodig heeft, zonder dat er iets wordt weggelaten. De rest van deze pagina is de referentie voor elk stuk; dit is iets dat je eerst moet kopiëren en dan moet bezuinigen.
post hieronder is je eigen JSON helper — hij gooit op een niet-2xx en passeert signal er doorheen, dus de spil leest als het contract in plaats van als HTTP.
const correlations = {
id: 'correlations', // the provenance tag written on everything it lands
label: 'Correlations', // shown verbatim, so translate it yourself
maxCandidates: 2000, // refuse to fetch while the count is above this
// Which nodes this offers itself for — return the ones you accept, and a mixed
// selection runs it against just those. Omit it and it applies to everything.
appliesTo: nodes => nodes.filter(node => node.getData()?.type !== 'case'),
// The cheap call: what is out there, and what you could narrow by.
summarize: async (nodes, narrowing, { signal }) => {
const { total, byType } = await post('/api/correlations/count', {
ids: nodes.map(node => node.id),
types: narrowing.type ?? [], // pass the narrowing on so the count tracks it
}, signal)
return {
total, // judged against maxCandidates
facets: [{
key: 'type', // the key you read back out of `narrowing`
label: 'Type',
type: 'multiselect',
options: byType.map(row => ({ label: row.label, value: row.value, count: row.count })),
}],
}
},
// The expensive call: a flat fragment, run only on a number the analyst agreed to.
fetch: async (nodes, narrowing, { signal }) => {
const { items } = await post('/api/correlations', {
ids: nodes.map(node => node.id),
types: narrowing.type ?? [],
}, signal)
return {
nodes: items.map(item => ({
id: item.uuid, // an id already on canvas is skipped, never overwritten
data: { label: item.value, type: item.type, seen: item.first_seen },
})),
edges: items.map(item => ({
from: item.origin_uuid, // both endpoints must land for the edge to land
to: item.uuid,
data: { type: 'correlation' },
})),
}
},
// The write half, and the only optional one here. Omit it and this pivot's results
// are *not savable* — never counted unsaved, and no Save offered. See below.
async save({ origin, nodes, edges }, ctx) {
const written = await post('/api/correlations/save', {
event: origin[0]?.id,
nodes: nodes.map((node) => node.getData()),
}, ctx.signal)
return {
savedNodeIds: written.ok,
savedEdgeIds: edges.map((edge) => edge.id),
message: written.refused ? `${written.refused} refused by the server` : undefined,
}
},
}
new Pivotick(document.querySelector('#graph'), data, { pivots: [correlations] })Vier dingen die gemakkelijk fout kunnen gaan, allemaal hierboven zichtbaar:
narrowingis aan jou. Het arriveert als{ [facetKey]: value }, met behulp van de toetsen uw eigen facetten verklaard. Het negeren ervan is legaal, maar dan beweegt de teller nooit en draait hij om over de dop kan nooit worden gedeblokkeerd.signalis geen optionele beleefdheid. Het verlaten van de draaimodus of het wijzigen van de oorsprong wordt afgebroken vragen tijdens de vlucht. Geef het door aan elk verzoek, anders betaal je voor antwoorden waar niemand op zit te wachten voor.ctx.isStale()is dezelfde controle voor transporten die geen signaal aannemen.- Gooi voor een mislukking, retourneer leeg voor een leeg. Een gegooide fout verschijnt op het draaipunt invoer met een Opnieuw proberen.
{ total: 0 }is een eerlijk "niets daarbuiten", en de twee lezen heel anders dan een analist. - Zeg als je het niet weet. Een bron die live wordt gevraagd, heeft mogelijk geen telling voordat hij antwoordt. Retourneer
{ total: null, facets }: er wordt niet geteld,maxCandidatesweigert het niet, encandidateCeilingbegrenst nog steeds watfetchretourneert.0zou beweren dat er niets is. - Ids zijn de dedup-sleutel. Retourneert de stabiele ID van het bronsysteem, niet een ID per antwoord. of bij elke herhaling komen dezelfde knooppunten opnieuw terecht als nieuwe kandidaten.
Het leverancierscontract
interface PivotDefinition {
id: string // provenance tag, menu key, triage key
label: string // used verbatim, so it can be translated
icon?: string // trusted SVG, injected as-is
origin?: 'selection' | 'none'
appliesTo?: (nodes: Node[]) => boolean | Node[]
summarize?: (nodes: Node[], narrowing: PivotNarrowing, ctx: PivotContext) => PivotSummary | Promise<…>
fetch: (nodes: Node[], narrowing: PivotNarrowing, ctx: PivotContext) => PivotResult | Promise<…>
autoIngest?: boolean
maxCandidates?: number
save?: (payload: PivotSavePayload, ctx: PivotSaveContext) => PivotSaveOutcome | Promise<…>
autoSave?: boolean
}Beide oproepen hebben een array knooppunten nodig, dus een draai over vijftig ervan is één backend-verzoek in plaats van vijftig. Beide nemen de huidige narrowing. Beiden krijgen een PivotContext uitvoering signal en isStale(), hetzelfde annuleringspatroon dat elke asynchrone hook in de bibliotheek gebruikt.
appliesTo: de hele oorsprong, of een deel ervan
Retourneert een boolean voor een regel over de oorsprong als geheel, en de **knooppunten waarvoor u ** accepteert een regel die één knooppunt tegelijk leest. Een lege array betekent hetzelfde als false.
appliesTo: nodes => nodes.length >= 2 // whole origin
appliesTo: nodes => nodes.filter(n => n.getData()?.type === 'domain') // per nodeDe vorm per knooppunt is van belang zodra een selectie gemengd is: een domein en een IP samen gekozen elk behoudt zijn eigen providers in plaats van alleen degenen over te laten die beide accepteren, en de paneel zegt dit bij de invoer — *Geldt voor 3 van de 5 gekozen *.
Wat het ook bewaart, het is de oorsprong waarmee de provider wordt aangeroepen: summarize en fetch nooit zien een knooppunt dat is afgewezen, en de in de cache opgeslagen samenvatting wordt gecodeerd door die beperkte oorsprong. Het wordt herlezen bij elke oorsprongsverandering, dus houd deze synchroon en goedkoop.
graph.pivots.for(nodes) // everything that applies, partially included
graph.pivots.originFor('whois', nodes) // the share this one would run onDoor run aan te roepen met een oorsprong die een draaipunt verwerpt, wordt 'failed' volledig opgelost in plaats van opgehaald op een lege oorsprong - een run die er goed uitzag en niets antwoordde, zou erger zijn.
summarize: de goedkope
Volledig weergegeven onder Een complete aanbieder. De total is het getal de de dop wordt beoordeeld en de facets worden de vernauwingsknoppen: u geeft de vorm aan, de bibliotheek tekent de widgets. Geef de vernauwing door aan uw backend, zodat de telling bijhoudt wat koos de analist, anders kan de poort nooit opengaan.
Een facet kan een default declareren: de optiewaarden a multiselect beginnen met aangevinkt, of de waarde a select of boolean begint bij. Het paneel tekent het en Duidelijke vernauwing keert terug naar maar de sleutel blijft buiten de vernauwing zolang deze vastzit, dus uw provider moet a lezen ontbrekende sleutel als standaard. Een geleegde multiselect met een standaardwaarde wordt verzonden als [], wat betekent geen.
{ key: 'element', label: 'Element', type: 'multiselect', default: ['attribute', 'object'],
options: [/* attribute, object, tag, … */] }Laat summarize volledig weg en het draaipunt biedt geen telling en geen vernauwing, alleen een Run knop. Dat is legaal, en dan moet fetch veilig blind kunnen worden genoemd, omdat niets kan doorbreken het.
Tellingen zijn adviserend. Altijd.
summarize retourneert een claim, geen contract, en het verschilt legitiem van wat er wordt opgenomen landen: eerst ontdubbelen, dan toestemmingen, oudheid en aanbieders die opzettelijk bij benadering komen. De gebruikersinterface markeert het verschil met een tilde: ~2,143 correlations is het nummer van de provider, terwijl 210 fetched en 12 selected eigendom zijn van de bibliotheek. Een psychiater is nooit een fout, en a telling is nooit dragend voor de indeling.
fetch: de echte
Geeft een plat fragment terug: { nodes: RawNode[], edges: RawEdge[] }. Geen geretourneerde knooppuntnamen an bestaande ouder op het canvas. Nesten reist in RawNode.children, dus een container arriveert als a nieuw knooppunt met zijn eigen subboom. Een edges-only resultaat is legaal: randen waarvan de eindpunten staan allemaal al op canvas en worden hun eigen triagerijen.
Facettypen
Bij vernauwing wordt gebruik gemaakt van elk facettype dat de query-engine kent, behalve regex, wat geen enkele backend kan wordt gevraagd om te evalueren: text, select, multiselect, numberRange, boolean. Regex leeft in de eigen filters aan de clientzijde van het triagevenster, waar de rijen al in de hand zijn.
Hoe het paneel ze tekent en waar de doorslaglijn vandaan komt
Een multiselect wordt getekend als een lijst met selectievakjes bij elke optie en de bijbehorende count op het scherm, zodat de getallen die u verkleint zichtbaar blijven terwijl u verkleint. Een enkele keuze select blijft een vervolgkeuzelijst en bevat de tellingen in de optielabels.
Onder het totaal drukt het paneel af waar het van gemaakt is, afkomstig uit de eerste multiselect facet: deze opties verdelen het resultaat. Zodra dat facet is gekozen, verzonden of standaard, alleen de gekozen opties worden vermeld. De tellingen van een facet met één keuze zijn alternatieven in plaats van delen, dus ze worden daar niet opgeteld.
Gating: de dop en het plafond
maxCandidates: 2000 // per pivot: refuse to fetch while the count exceeds it
new Pivotick(el, data, { pivotCandidateCeiling: 10_000 }) // absolute, all pivotsBeiden weigeren, en geen afkapsels of monsters. Een weigering houdt altijd drie dingen in volgorde: het aantal, de limiet en de weg vooruit. 'Te veel resultaten' zonder getal is dat niet iets waar een analist op kan reageren.
De limiet wordt beoordeeld op basis van de meest recente telling voor de huidige vernauwing, wat deze toelaat optillen. Verklein van 2.143 naar 210 en Fetch wordt vanzelf ingeschakeld. Het plafond gaat over herinnering voor kandidaat-objecten in plaats van over de tafel, die virtualiseert.
Kandidaten zijn niet de grafiek
Niets dat een draaipunt retourneert, staat in de grafiek, in de gegevenstabel of in welk facet dan ook wordt ingeslikt. Resultaten die voor triage zijn geënsceneerd, openen het tabblad Review van het dock: één venster per draaipunt, weergegeven als verticaal tabbladen langs de zijkant, elk met zijn eigen telling en zijn eigen uitweg - met die van de provider kolommen, de filters van de gegevenstabel, sorteren, paging en een ingest-actie.
- De afwijzing is expliciet en wordt onthouden voor de sessie, ingetoetst per draaipunt. De volgende run biedt die kandidaat niet opnieuw aan, en de kopregel geeft aan hoeveel er zijn onderdrukt. EEN De afgewezen rij wordt op zijn plaats doorgehaald in plaats van verplaatst, en blijft omkeerbaar.
- Wat een draaipunt tegenhoudt, staat vermeld bij de vermelding in het deelvenster Draaipunt, genaamd tabel heeft deze naam genoemd, met restore op elke rij en Restore all eronder. Het blijft daar zodra de ruit gesloten is, zodat een afwijzing kan worden heroverwogen zonder het draaipunt te hoeven draaien opnieuw om het te vinden.
- Knooppunten en randen zijn afzonderlijke blokken, elk genoemd en geteld wanneer een run beide retourneert. Een resultaat met alleen randen is een eigen tabel, geen leeg venster.
- Een containerrij gaat open. Deze bevat een Kinderen telling van wat er direct in zit, en een Caret geeft de inhoud weer, met de gedeelde kenmerken van elk kind en een notitie waar een kind zich bevindt zelf een container. Het openen van een rij markeert deze niet, en er kan niets in de rij worden geplukt eigen - het opnemen van de rij neemt de hele container in beslag.
- Het sluiten van een provider wijst niets af. Niet-gesorteerde restjes komen terug bij de volgende run. Weiger alle resterende is het enige gebaar dat ze weggooit.
- Een herhaling vervangt het venster van die provider. Als u rijen gemarkeerd heeft, wordt dit vermeld en worden er aanbiedingen aangeboden Nieuwe tonen / Blijf triage, in plaats van je triage ongevraagd weg te gooien.
- Met Opname in een groep worden de geselecteerde rijen gevouwen, één groep per type, buiten de oorsprong geplaatst. Zie Pivotlandingen. Het wordt aangeboden tenzij
UI.simplifyis uitgeschakeld. MetpivotIngestGrouped: truewordt elke landing gegroepeerd, evenals de knop luidt in plaats daarvan Ingest loose.
Alles wat het venster doet, is ook programmatisch bereikbaar:
graph.pivots.candidates('correlations') // the staged set
graph.pivots.mark('correlations', id) // …markAll / reject / rejectRemaining
await graph.pivots.ingest('correlations') // commit the marked ones
await graph.pivots.ingest('correlations', 'triage', { group: true }) // …folded, one group per type
graph.pivots.discard('correlations') // close it; rejects nothing
graph.pivots.rejectedRows('correlations') // what the session is holding back
graph.pivots.unreject('correlations', id) // …unrejectAll for every one of themautoIngest
Voor een klein, vertrouwd resultaat waar niemand doorheen wil prikken, zoals het uitbreiden van een container in zijn dozijn kinderen, verklaar autoIngest: true. De resultaten komen direct terecht, en ook de bovenste balk ongedaan maken neemt ze terug zoals elke andere inname. De aanbieder bepaalt dit, want alleen hij weet het of de eigen resultaten klein en betrouwbaar genoeg zijn om triage over te slaan.
Het niet instellen ervan is niet hetzelfde als false. Er staat dat het draaipunt geen zicht heeft, waardoor er een draaipunt met één klik vrij om alleen de grootte te bepalen; false zegt resultaten heeft altijd ogen op hen nodig, en wordt vereerd, hoe de run ook werd gestart.
autoIngest: true // always lands
autoIngest: false // always reviewed
// unset: a one-click run decides on size
new Pivotick(el, data, { pivotQuickIngestLimit: 50 }) // that size, all pivotsWelk land dan ook, van hier of van Review, kan opgevouwen aankomen landingsgroepen in plaats van losse:
new Pivotick(el, data, { pivotIngestGrouped: true }) // every landing, one group per typeInslikken, en wat het mag doen
Eén gebaar, één batch, één dataBatchChanged, in deze volgorde:
- Dedup — een ID die al op canvas staat, wordt overgeslagen en nooit overschreven, ongeacht of deze er al was toen de kandidaten werden opgevoerd of een andere run landde terwijl ze wachtten.
- Kindervereniging op id.
- Plaatsing nabij het oorsprongsknooppunt, verstoord. De eigen
x/yvan een aanbieder wint, en een oorsprongsloze run-zaden in het viewport-centrum. - Herkomst, waarna de batch landt.
Inname is puur additief. De enige dingen die ooit worden verwijderd zijn removeBySource en uitvoeren ongedaan maken.
Eén poort, één keer aangeroepen met de hele set:
callbacks: {
onBeforeIngest: async ({ pivotId, origin, candidates, trigger, confirm }) => {
if (candidates.nodes.length < 50) return true
return await confirm({ title: `Add ${candidates.nodes.length} nodes?` })
},
}Geef false terug om een veto uit te spreken, of { accept: true, nodes, edges } om een subset binnen te halen. Een weggelaten sleutel betekent "zoals gevraagd", precies zoals onBeforeDelete luidt.
Herkomst
Elk knooppunt en elke rand draagt de set van bronnen die ervoor instaan. Een setje in plaats van een scalair, omdat twee overlappende draaipunten op één knooppunt normaal zijn. Met een scalair is de De tweede die arriveert, wist de claim van de eerste, en als je een van beide verwijdert, wordt het knooppunt meegenomen het.
node.getSources() // ['seed', 'correlations'], where 'seed' is the loaded data
node.hasSource('correlations')
edge.getSources() // edges carry it too, which is the load-bearing half
graph.removeBySource('correlations') // drop the tag; delete only when the set emptiesEven terugrennen
Een ingest is één invoer in graph.history, naast de andere dingen die veranderen wat de canvas bevat: verwijderingen, duurzame huiden en met de hand getekende elementen.
graph.history.entries() // newest first; a pivot entry's `id` is its runId
graph.history.undo() // the newest entry
graph.history.undo(runId) // that ingest, and contiguously anything done since
graph.history.redo() // re-lands the recorded delta; no refetch, no re-gatingOngedaan maken is aaneengesloten: als u op een ouder item richt, wordt ook elk item erboven teruggedraaid, één partij. Het omkeren van één oude run op zichzelf is graph.removeBySource(pivotId), wat daalt die bron garandeert en verwijdert alleen waar niets anders voor instaat: een voorwaartse operatie, geregistreerd als één.
Een gedeeltelijke opname uit één gefaseerde set krijgt zijn eigen runId, dus elke batch is een afzonderlijke binnenkomst. En als je een opname ongedaan maakt die nog steeds de nieuwste invoer ** is, worden de kandidaten er weer in geplaatst het beoordelingsvenster** in plaats van de provider er opnieuw om te vragen. Zie Ongedaan maken en geschiedenis voor het geheel.
Resultaten opslaan
Ingest zet kandidaten op het canvas; het schrijft ze nergens. Een spil die verklaart save kan zijn eigen resultaten terugsturen naar het systeem waar ze vandaan komen, en de bibliotheek bewaart de grootboek: welke elementen een run heeft gemaakt, of ze zijn geschreven, welke zijn mislukt, en wat een nieuwe poging zou moeten inhouden.
Laat save weg en de resultaten van de pivot zijn niet op te slaan. Ze komen nooit in het grootboek terecht, maar nooit geteld als ze niet zijn opgeslagen, en er verschijnt geen Save voor hen. Dat is de juiste verklaring voor een spil over afgeleide gegevens – de uitvoer van een correlatie-engine is niet aan jou om terug te schrijven – en dat is het ook stopt een permanente "210 niet opgeslagen" zonder oplossing.
Het geheel, inclusief gedeeltelijke schrijfbewerkingen, nieuwe pogingen, de id's die een bronsysteem mint en wat dan ook ongedaan maken zal wel en zal niet bereiken: Pivotresultaten opslaan.
De Pivot rail-modus
Gebruik één om over het oppervlak te lopen. Wat er toe doet als u configureert, in plaats van het besturen: het betreden van de modus is de bedoeling die een provider belt – net als vasthouden Draaien ▸ open in het contextmenu – hierdoor stopt elke vraag tijdens de vlucht, en selectie alleen kost niets. Selectie is ook het gebaar voor slepen, stylen en bulken edit, zodat de bibliotheek nooit speculatief een provider belt.
De modus is gated in het register:
UI: { pivotMode: 'auto' } // default: the button exists only while a pivot is registered
UI: { pivotMode: true } // force it, for pivots that arrive asynchronously
UI: { pivotMode: false } // neverEen consument die geen pivots registreert, ziet dus geen spoor van het kenmerk. Dat is het nooit gemonteerd in de modus viewer of static.
Oorsprongloze draaipunten
Sommige verrijkingen hebben geen knooppunt waarop ze kunnen worden uitgevoerd, zoals zoeken, importeren of een lijst plakken indicatoren. Declareer origin: 'none' en de spil krijgt [], is van toepassing als de oorsprong leeg, en vouwt zich op tot een Zonder oorsprong groep zodra er één is gekozen. Resultaten route door dezelfde triageruit, dezelfde poort en hetzelfde herkomstmodel, en ze landen op de uitzichtpunt centrum.
appliesTo is voor één hiervan betekenisloos en wordt niet geraadpleegd.
Aangegeven potentieel
Een hint op de rand van het knooppunt, die zegt: "Er zijn hier 2100 correlaties", daar geplaatst door wie dan ook de gegevens geladen.
node.setPotential('correlations', 2100) // 0 clears it
node.getPotential('correlations')
node.setPotential(2199) // the total across every pivot
node.getPotential()Het is declared, nooit opgevraagd. De bibliotheek zal geen aanbieder bellen om een badge te trekken, omdat een telling die zich op één knooppunt voordeed op het moment dat ernaar werd gevraagd, de canvas dat twee verschillende verhalen vertelt. Als u op de badge klikt, wordt de draaimodus geopend die hierop is afgestemd draai.
Net als elke andere setter op Node markeert het het knooppunt als vuil: bel graph.renderer.update() als er niets anders op het punt staat te renderen.
Wat de rand trekt
Standaard worden de rim-badges alleen weergegeven als de draaimodus geopend is, waar ze helpen bij het kiezen van een oorsprong; Als u daar op één klikt, wordt het paneel naar dat knooppunt en draaipunt geleid. pivotRimBadgeVisible verandert wanneer ze worden weergegeven:
new Pivotick(el, data, { pivots, pivotRimBadgeVisible: 'always' })
graph.pivots.rimBadgeVisible = 'pivot-mode' // or later; it dirties every node'pivot-mode' (standaard) | Alleen als de Pivot-railmodus geopend is. |
'always' | Wat de modus ook is, een badge is dus ook een manier om naar de Pivot-modus te gaan. |
'never' | Helemaal niet. |
Eenmaal getoond, is hun vorm de volgende keuze.
Een knooppunt heeft vier randhoeken, en slechts twee als er kinderen zijn: de uitbreidingsafkoop behoudt de oostzijde. Eén badge per aanbieder is dus bij een handjevol leesbaar en bij niet mogelijk honderd. pivotRimBadge kiest de vorm:
new Pivotick(el, data, { pivots, pivotRimBadge: 'summary' })
graph.pivots.rimBadge = 'per-pivot' // or later; it dirties every node'per-pivot' (standaard) | Eén badge per draaipunt die een potentieel aanduidde, waarbij elke draaipunt werd geopend. Verschillende ervan vallen al vroeg in een knooppunt met kinderen samen in een +n. |
'summary' | Eén badge, ongeacht de provider. Het toont het totaal dat is gedeclareerd zonder spil-ID, of – zonder dat er iets is gedeclareerd – hoeveel draaipunten er van toepassing zijn. |
'off' | Niets. NodeStyle.badges trekt nog steeds. |
Wat een summary-badge doet als erop wordt geklikt, en waar de telling vandaan komt
In summary is de badge één gebaar: hij opent het draaipaneel op dat knooppunt, omdat op elk echte aanbieder telt het panel is waar de tellingen en de keuze leven. De uitzondering is een knooppunt waar precies één draaipunt van toepassing is en, wordt nee summarize verklaard - niets om eerst te lezen en niets te smal - waar de klik het uitvoert. Waar het resultaat terechtkomt, is de eigen oproep van de provider: autoIngest beslist tussen het canvas en het triagevenster, zoals overal.
Het aantal toegepaste draaipunten wordt afgeleid en niet gedeclareerd, zodat er geen telefoontje naar de provider nodig is. Het wordt gehouden tussen grafiekwijzigingen en vernieuwing wanneer het register of de knooppunten van de grafiek bewegen; een appliesTo iets anders lezen kan op de rand achterblijven, en het paneel is altijd het exacte antwoord.
Caching
De bibliotheek bewaart één ding: summarize resultaten, ingetoetst op (draaipunt, oorsprong, vernauwing), omdat een samenvatting met meerdere selecties een aggregaat is dat door niets kan worden ontleed. Alles anders is van jou:
graph.pivots.invalidate() // all of it
graph.pivots.invalidate('correlations') // one pivot's
graph.pivots.invalidate('correlations', nodes) // only what was asked about theseAuth, opnieuw proberen, snelheidsbeperking en eventuele eigen cache behoren tot de functies van uw provider, dit zijn eenvoudige functies die je hebt geschreven.
Wat uw bron te bieden heeft
De bovenstaande pagina's zijn voor degene die de provider schrijft. Dit is hetzelfde contract, gelezen uit de andere kant, voor degene die eigenaar is van de dienst die het oproept.
- Een ophaaloproep, waarbij de objecten en hun relaties worden geretourneerd. De enige vereiste. Twee dingen eraan zijn belangrijk: er zijn veel id's nodig in één verzoek, dus een draai over vijftig knooppunten kost één gesprek, en de id's die het retourneert zijn stabiel over runs, want dat is wat dedup-toetsen aan. Een per-response-ID levert de resultaten van gisteren opnieuw op als nieuwe kandidaten.
- Een teloproep, waarbij dezelfde ID's en dezelfde filters worden gebruikt, een totaal wordt geretourneerd en de per waarde telt voor alles wat kan worden beperkt. Het is wat de poort en de het werk wordt beperkt en bij elke wijziging wordt er opnieuw naar gevraagd, dus het moet goedkoop zijn. Bij benadering is prima: tellingen zijn adviserend. Zonder één A pivot draait nog steeds, met een kale Run en niets om het te openen.
- Dezelfde filters worden door beide gehonoreerd. Een telling die ze negeert, beweegt nooit, dus een draaipunt over de dop kan nooit worden gedeblokkeerd.
- Een manier om te annuleren. Vragen worden verlaten wanneer de analist verder gaat, en de
signalde aanbieder wordt overhandigd is alleen de moeite waard om door te geven als het transport daarop inwerkt. - Een schrijfoproep, als u de resultaten kunt terugschrijven. Het zou de ID's moeten retourneren toegewezen, zodat
canonicalIdskan stoppen de run van morgen, waarbij wordt gedupliceerd wat er is bespaard, en een gedeeltelijk succes kan worden gerapporteerd.
Beide leesoproepen zouden een leeg antwoord moeten opleveren, afgezien van een mislukking: er is geen resultaat de gegevens, een fout is een feit over de service, en ze lezen heel anders dan een analist.
Niets hier heeft paginering, een cursor of streaming transport nodig. Vernauwing is wat vervangt zij.
Wat dit niet is
- Geen streaming en geen servercursor. Door te verkleinen worden ze vervangen: in plaats van er twee op te halen duizend rijen, vraag wat er staat en laat de analist kiezen. Het contract vereist nooit een streaming backend, omdat veel bronnen er geen hebben.
- Geen her-ouderschap. Een geretourneerd knooppunt geeft nooit een bestaande ouder een naam. Kindervereniging op id is de enige manier waarop ingest de kinderen van een bestaand knooppunt raakt.
- Geen bewerking van eigenschappen ongedaan gemaakt.
graph.historydekt wat het canvas bevat en laat zien — wat kwam binnen, wat ging eruit, wat verborgen is. De gegevens van een knooppunt hebben de backend-status die de bibliotheek niet had auteur, dus het lokaal terugzetten van een veld is de taak vanonBeforeNodeEditCommit, niet de onze. - Geen transportbeleid.
saveschrijft terug, maar inloggegevens, nieuwe pogingen, snelheidsbeperking en conflictdetectie zijn allemaal van de consument. De enige nieuwe poging van de bibliotheek is het aandringen van analisten Opnieuw proberen. - Geen afwijzingsgeheugen tijdens een herlaadbeurt. Een afwijzing is een oordeel in de context van één sessie. en dezelfde kandidaat kan in een andere grafiek een ander antwoord waard zijn. Afwijzingen zijn dat wel gehouden voor de sessie en niet verder.
- Geen vernieuwing van wat er al is. Een kandidaat met een ID-match verlaat het bestaande knooppunt onaangeroerd; Voor het afstemmen van een knooppunt op een nieuwere kopie is een conflictbeleid van de bibliotheek nodig heeft niet.