我希望使用Neo4j将大量文件名导入图形数据库。数据来自外部源,可在CSV文件中使用。我想从数据中创建一个树结构,这样我可以在以后轻松地“导航”查询中的结构(即查找某个目录下的所有文件,所有文件出现在多个目录中等)。
因此,给出示例输入:
/foo/bar/example.txt
/bar/baz/another.csv
/example.txt
/foo/bar/onemore.txt
我想创建以下图表:
( / ) <-[:in]- ( foo ) <-[:in]- ( bar ) <-[:in]- ( example.txt )
<-[:in]- ( onemore.txt )
<-[:in]- ( bar ) <-[:in]- ( baz ) <-[:in]- ( another.csv )
<-[:in]- ( example.txt )
(其中每个节点标签实际上是一个属性,例如路径:)。
使用固定数量的目录级别时,我已经能够达到预期的效果;例如,当每个文件的深度为三级时,我可以创建一个包含4列的CSV文件:
dir_a,dir_b,dir_c,file
foo,bar,baz,example.txt
foo,bar,ban,example.csv
foo,bar,baz,another.txt
使用密码查询导入它:
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)
但是我希望有一个适用于任何级别的子目录(以及一个数据集中的级别组合)的通用解决方案。请注意,如果需要,我可以预处理输入,因此我可以在输入CSV文件中创建任何所需的结构。
我看过要点或插件,但似乎找不到有用的东西。我想/希望我能用split()函数做一些事情,即使用split('/',row.path)获取路径元素列表,但我不知道如何处理这个列表一系列MERGE运营。
答案 0 :(得分:1)
这是第一次更广泛的切入。
前提是您可以将完全限定的路径拆分为组件,然后使用它的每个组件来拆分路径,以便为较大路径的每个单独组件构建完全限定的路径。使用此键作为合并项目的键,并在合并后设置单个组件。如果某些东西不是根级别,那么找到单个组件的父级并创建回到它的关系。如果完全限定路径中存在重复的组件名称,则会中断。
首先,我首先在fq_path
create constraint on (c:Component) assert c.fq_path is unique;
这是加载声明。
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 *
如果要区分文件和文件夹,可以在此处运行一些查询,以便在相应节点上设置另一个标签。
查找文件并将其设置为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
找到文件夹并将其设置为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