2016-07-28 2 views
2

Ich suche, viele Dateinamen in eine Diagrammdatenbank zu importieren, mit Neo4j. Die Daten stammen von einer externen Quelle und sind in einer CSV-Datei verfügbar. Ich würde gerne eine Baumstruktur aus den Daten erstellen, so dass ich später in Abfragen leicht die Struktur "durchnavigieren" kann (d. H. Finde alle Dateien unterhalb eines bestimmten Verzeichnisses, alle Dateien, die in mehreren Verzeichnissen vorkommen usw.).Wie kann man eine Verzeichnis-/Dateistruktur in Neo4j aus einer CSV-Datei importieren?

So, das Beispiel Eingabe gegeben:

/foo/bar/example.txt 
/bar/baz/another.csv 
/example.txt 
/foo/bar/onemore.txt 

Ich mag würde das folgende Diagramm erstellen:

(/) <-[:in]- (foo) <-[:in]- (bar) <-[:in]- (example.txt) 
             <-[:in]- (onemore.txt) 
     <-[:in]- (bar) <-[:in]- (baz) <-[:in]- (another.csv) 
     <-[:in]- (example.txt) 

(wobei jeder Knoten-Label ist eigentlich ein Attribut, z.B. Pfad :).

Ich konnte den gewünschten Effekt erzielen, wenn ich eine feste Anzahl von Verzeichnisebenen verwende; zum Beispiel, wenn jede Datei auf drei Ebenen tief ist, konnte ich eine CSV-Datei mit 4 Spalten erstellen:

dir_a,dir_b,dir_c,file 
foo,bar,baz,example.txt 
foo,bar,ban,example.csv 
foo,bar,baz,another.txt 

Und es importieren, um eine Chiffre Abfrage:

LOAD CSV WITH HEADERS FROM "file:///sample.csv" AS row 
    MERGE (dir_a:Path {name: row.dir_a}) 
    MERGE (dir_b:Path {name: row.dir_b}) <-[:in]- (dir_a) 
    MERGE (dir_c:Path {name: row.dir_c}) <-[:in]- (dir_b) 
    MERGE  (:Path {name: row.file}) <-[:in]- (dir_c) 

Aber ich möchte haben eine allgemeine Lösung, die für jede Ebene von Unterverzeichnissen (und Kombinationen von Ebenen in einer Datenmenge) funktioniert. Beachten Sie, dass ich meine Eingaben bei Bedarf vorverarbeiten kann, damit ich jede gewünschte Struktur in der Eingabe-CSV-Datei erstellen kann.

Ich habe Gists oder Plugins angeschaut, kann aber nichts finden, was funktioniert. Ich denke/hoffe, dass ich in der Lage sein sollte, etwas mit der Funktion split() zu tun, dh mit split ('/', row.path) eine Liste von Pfadelementen zu erhalten, aber ich weiß nicht, wie ich diese Liste verarbeiten soll eine Kette von MERGE-Operationen.

Antwort

1

Hier ist ein erster Schnitt an etwas allgemeiner. Die Prämisse besteht darin, dass Sie den vollständig qualifizierten Pfad in Komponenten aufteilen und dann jede Komponente davon verwenden können, um den Pfad zu teilen, sodass Sie den vollständig qualifizierten Pfad für jede einzelne Komponente des größeren Pfads strukturieren können. Verwenden Sie dies als Schlüssel zum Zusammenführen von Elementen und zum Festlegen der einzelnen Komponenten nach dem Zusammenführen. Falls etwas nicht die Root-Ebene ist, suchen Sie das übergeordnete Element einer einzelnen Komponente und erstellen Sie die Beziehung zurück zu ihr. Dies wird fehlschlagen, wenn doppelte Komponentennamen in einem vollständig qualifizierten Pfad vorhanden sind.

Zuerst begann ich auf eine Eindeutigkeitsbedingung, indem fq_path

create constraint on (c:Component) assert c.fq_path is unique; 

Hier ist die Ladeanweisung.

load csv from 'file:///path.csv' as line 
with line[0] as line, split(line[0],'/') as path_components 
unwind range(0, size(path_components)-1) as idx 
with case 
     when idx = 0 then '/' 
    else 
     path_components[idx] 
    end as component 
    , case 
     when idx = 0 then '/' 
    else 
     split(line, path_components[idx])[0] + path_components[idx] 
    end as fq_path 
    , case 
     when idx = 0 then 
     null 
     when idx = 1 then 
     '/' 
    else 
     substring(split(line, path_components[idx])[0],0,size(split(line, path_components[idx])[0])-1) 
    end as parent 
    , case 
     when idx = 0 then 
     [] 
     else 
     [1] 
    end as find_parent 
merge (new_comp:Component {fq_path: fq_path}) 
set new_comp.name = component 
foreach (y in find_parent | 
    merge (theparent:Component {fq_path: parent}) 
    merge (theparent)<-[:IN]-(new_comp) 
)  
return * 

Wenn Sie hier zwischen Dateien und Ordnern zu unterscheiden sind ein paar Fragen, die Sie später ein anderes Etikett auf dem jeweiligen Knoten setzen ausgeführt werden können.

die Dateien finden und sie als File

// find the last Components in a tree (no inbound IN) 
// and set them as Files 
match (c:Component) 
where not (c)<-[:IN]-(:Component) 
set c:File 
return c 

die Ordner finden und sie als Folder

// find all Components with an inbound IN 
// and set them as Folders 
match (c:Component) 
where (c)<-[:IN]-(:Component) 
set c:Folder 
return c 
Verwandte Themen