Filtrare e aggregare i dati del grafo in Microsoft Fabric

L'applicazione di filtri restringe i risultati alle righe importanti. L'aggregazione riepiloga tali righe in conteggi, totali e medie. Questo articolo illustra come applicare entrambe le tecniche nelle query GQL sul grafico in Microsoft Fabric.

Gli esempi usano il dataset di esempio del social network. Per una spiegazione completa del flusso delle query e delle istruzioni, consulta la guida al linguaggio GQL.

Usa questo articolo per il filtraggio di righe e modelli, l'aggregazione raggruppata e non raggruppata, i filtri specifici per le aggregazioni e l'instradamento condizionale. Per costruire pattern multihop e selezionare i percorsi, vedi Write graph pattern queries. Per attività aziendali facilmente adattabili, consulta Scrivere query GQL comuni.

Prerequisiti

Filtrare le righe con il comando FILTER

Utilizzare FILTER per mantenere solo le righe che soddisfano una condizione. Posizionare FILTER dopo MATCH per restringere i risultati corrispondenti.

La query seguente restituisce tutte le femmine con il nome e il compleanno:

MATCH (p:Person)
FILTER p.gender = 'female'
RETURN p.firstName, p.lastName, p.birthday

Combinare più condizioni con AND e OR. Ad esempio, la query seguente restituisce i nomi di tutte le femmine nate prima del 1990:

MATCH (p:Person)
FILTER p.gender = 'female' AND p.birthday < 19900101
RETURN p.firstName, p.lastName

Tip

Usa una clausola in linea WHERE quando la condizione definisce quale nodo o arco può partecipare alla corrispondenza. Da usare FILTER quando la condizione si applica alla riga prodotta da un'affermazione precedente. La posizione dei predicati può modificare i risultati del percorso più breve; vedi Posiziona predicati prima o dopo la selezione del percorso.

Filtrare durante la corrispondenza dei criteri

Le clausole inline WHERE all'interno di un MATCH pattern limitano quali nodi e archi possono essere idonei alla corrispondenza. L'ottimizzatore di query può applicare predicati equivalenti durante la scansione, quindi la sintassi inline non è intrinsecamente più veloce di un separato FILTER. Scegli la forma che esprime la semantica prevista.

Ad esempio, per trovare persone nate prima del 1994 insieme all'azienda in cui lavorano, limitando i risultati alle aziende il cui nome inizia con "A":

MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.name STARTS WITH 'A')
RETURN p.firstName, p.lastName, c.name

Filtrare le proprietà dei bordi nello stesso modo. Ad esempio, per restituire solo le persone che hanno iniziato a lavorare in una società nel 2000 o successivamente:

MATCH (p:Person)-[w:workAt WHERE w.workFrom >= 2000]->(c:Company)
RETURN p.firstName, p.lastName, c.name, w.workFrom

Per maggiori informazioni sulla scelta tra filtraggio inline e post-match, vedi Ottimizza le prestazioni delle query GQL.

Gestire i valori Null nei filtri

GQL usa la logica a tre valori: i predicati restituiscono TRUE, FALSEo UNKNOWN. Quando un valore della proprietà è Null, i confronti restituiscono UNKNOWN. FILTER UNKNOWN considera come non corrispondente, quindi la riga viene esclusa.

Usare IS NULL e IS NOT NULL per testare i valori Null in modo esplicito:

-- Only include people whose browser is known
MATCH (p:Person)
FILTER p.browserUsed IS NOT NULL
RETURN p.firstName, p.browserUsed

Usare coalesce() per sostituire un valore predefinito quando una proprietà potrebbe essere Null:

MATCH (p:Person)
RETURN p.firstName, coalesce(p.browserUsed, 'Unknown browser') AS browser

Caution

NULL = NULL restituisce UNKNOWN, non TRUE. Usare IS NULL sempre per verificare i valori Null, non per verificarne l'uguaglianza.

Aggregare i risultati con RETURN

Usare le funzioni di aggregazione in RETURN per riepilogare i risultati. Graph supporta le seguenti funzioni aggregate: COLLECT_ONE, COLLECT_ELEMENTS, COLLECT_LIST, MAX, MIN, AVG, SUM e COUNT.

Ad esempio, per contare tutte le persone nel grafico:

MATCH (p:Person)
RETURN count(*) AS totalPeople

Per contare valori distinti, ad esempio il numero di aziende distinte che impiegano persone:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN count(DISTINCT c) AS companyCount

Filtro di input per un aggregato

Aggiungi FILTER (WHERE predicate) dopo un aggregato per filtrare solo l'input di quell'aggregato. Gli altri aggregati nello stesso RETURN continuano a ricevere tutte le righe di input.

MATCH (p:Person)
RETURN count(*) AS allPeople,
       count(*) FILTER (WHERE p.birthday < 19900101) AS peopleBornBefore1990

Aggiungi LIMIT all'interno del filtro aggregato per usare al massimo quel numero di righe qualificate. La query applica il predicato prima del limite specifico dell'aggregato.

MATCH (p:Person)
RETURN count(*) FILTER (WHERE p.birthday < 19900101 LIMIT 100) AS sampleCount

Specifici per aggregato FILTER e LIMIT non rimuovono righe dal resto della query. Usa un'istruzione FILTER o una clausola match-level WHERE quando vuoi filtrare il flusso di riga.

Raccogli valori

Usare COLLECT_LIST per restituire un elemento di lista per ogni valore di input, inclusi i valori nulli. Aggiungi DISTINCT per rimuovere i duplicati.

MATCH (p:Person)
RETURN collect_list(DISTINCT p.browserUsed) AS browsers

COLLECT_ONE restituisce un valore di input non nullo. Il valore selezionato non è deterministico, quindi usalo solo quando qualsiasi valore del gruppo è accettabile.

COLLECT_ELEMENTS accetta input a valori di lista e concatena i loro elementi in un'unica lista:

MATCH (p:Person)
RETURN collect_elements([p.firstName, p.lastName]) AS names

Senza raggruppare colonne, una query aggregata senza righe di input restituisce una lista vuota da COLLECT_LIST e COLLECT_ELEMENTS e null da COLLECT_ONE.

Raggruppare i risultati con GROUP BY

Usare GROUP BY in RETURN per raggruppare le righe in base ai valori condivisi e alle aggregazioni di calcolo all'interno di ogni gruppo. Questo raggruppamento è l'equivalente GQL di SQL GROUP BY.

Ad esempio, per contare i dipendenti per azienda:

MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
ORDER BY employeeCount DESC

Raggruppare in base a più colonne e calcolare più aggregazioni contemporaneamente. Ad esempio, suddividere il numero di persone e l'intervallo di compleanno per sesso e browser, restituendo le 10 combinazioni più comuni:

MATCH (p:Person)
LET gender = p.gender
LET browser = p.browserUsed
RETURN gender,
       browser,
       count(*) AS personCount,
       min(p.birthday) AS earliestBirthday,
       max(p.birthday) AS latestBirthday
GROUP BY gender, browser
ORDER BY personCount DESC
LIMIT 10

Note

Tutte le espressioni non aggregate in RETURN devono essere visualizzate in GROUP BY. Le espressioni che non si trovano in GROUP BY devono usare una funzione di aggregazione.

Ordinare e limitare i risultati aggregati

Usare ORDER BY e LIMIT insieme a GROUP BY per trovare risultati top-N.

Ad esempio, per trovare le prime cinque città per numero di residenti:

MATCH (p:Person)-[:isLocatedIn]->(city:City)
LET cityId = city.id, cityName = city.name
RETURN cityId, cityName, count(*) AS residentCount
GROUP BY cityId, cityName
ORDER BY residentCount DESC
LIMIT 5

Importante

Posizionare ORDER BY prima LIMITdi . LIMIT si applica sempre al set di risultati già ordinato.

Indirizzare righe con istruzioni condizionali

Usa un'istruzione condizionale per instradare ogni riga in ingresso al primo ramo che corrisponde. L'input può provenire da qualsiasi fase precedente della query, non solo da un'aggregazione. Ad esempio, la seguente query categorizza le aziende dopo aver calcolato il numero di dipendenti:

MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
NEXT
WHEN employeeCount >= 100u THEN
  RETURN companyId, companyName, employeeCount, 'Large' AS category
WHEN employeeCount >= 10u THEN
  RETURN companyId, companyName, employeeCount, 'Medium' AS category
ELSE
  RETURN companyId, companyName, employeeCount, 'Small' AS category

I rami possono eseguire istruzioni di query complete e procedure annidate, anziché restituire solo espressioni. Il seguente esempio invia tre righe di input attraverso diverse forme di rami. Un ramo esegue un MATCH, un altro combina due aggregati con UNION ALL e poi ne aggrega i risultati, e il ramo di fallback restituisce una costante:

FOR selector IN [1, 2, 3]
RETURN selector
NEXT
WHEN selector = 1 THEN
  MATCH (:Person)-[:knows]->(:Person)
  RETURN count(*) AS total, 'Knows edges' AS category
WHEN selector = 2 THEN {
  MATCH (:Person)-[:workAt]->(:Company)
  RETURN count(*) AS partialCount
  UNION ALL
  MATCH (:Person)-[:studyAt]->(:University)
  RETURN count(*) AS partialCount
  NEXT
  RETURN sum(partialCount) AS total, 'Affiliation edges' AS category
}
ELSE
  RETURN 0u AS total, 'No selected metric' AS category

Il motore di query valuta i predicati in ordine per ogni riga. Gestisce solo il primo ramo corrispondente. Se un predicato valuta a UNKNOWN, la valutazione prosegue con il ramo successivo. Senza un ELSE, le righe che non corrispondono a un WHEN ramo vengono omesse.

Le affermazioni condizionali sono diverse dalle CASE espressioni. Graph supporta espressioni semplici CASE <expression> WHEN <value> per la selezione dei valori basata sull'uguaglianza. Le espressioni cercate CASE WHEN <predicate> non sono supportate. Per ulteriori informazioni, vedi Enunciati condizionali.