我的Neo4J数据库中有以下实体(使用版本2.0)。
Target
Library
Function
这些是各自之间的关系。
function[:used_in]->target
function[:included_in]->library
library[:part_of]->target
我的最终目标是在C#中构建一个树,它允许我表达目标中使用的函数之间的映射,但是可以将它们与它们的原始库相关联。在树中,库将表示为函数的父节点。
换句话说,假设一个库公开了10个不同的函数,但只有5个函数被(used_in)给定的目标使用。我只对那些5而不是其他人感兴趣。在每个功能的基础上,我希望能够快速(在我的树中)进入“包含”给定功能的库。我有目标集合,并了解我很可能必须为每个目标发出单独的查询。我的目标是避免为每个目标/库/功能发出多个查询。
鉴于我所描述的关系,是否有可能构建一个Cypher查询,它将返回我感兴趣的节点?
这是Cypher查询,它将返回给定目标的所有函数。
MATCH (function:Function)-[:used_in]->(target:Target)
WHERE (target.Name = "target.exe")
RETURN function
这是Cypher查询,它将返回给定函数的库。
MATCH (function:Function)-[:included_in]->(library:Library)
WHERE (function.Name = "foo")
RETURN library
我很想知道这是否可以组合成一个查询。在我当前的场景中,我需要为每个Function运行第二个查询。我希望我的关系足够优秀,以便减少我需要进行的查询次数。
我正在使用Neo4JClient - 如果有人帮助提供Cypher查询,我希望我能将它翻译成Neo4JClient。如果有人走得更远并给我C#代码,那就更好了,但请帮助我理解背后的Cypher。
以下是构建数据库的Cypher:
CREATE (t:Target { Name: 'Target.exe' })
CREATE (t:Target { Name: 'Target2.exe' })
CREATE (t:Target { Name: 'Target3.exe' })
CREATE (l:Library { Name: 'Library.lib', Path: 'i386' })
CREATE (l:Library { Name: 'Library.lib', Path: 'amd64' })
CREATE (l:Library { Name: 'Library2.lib', Path: 'amd64' })
CREATE (f:Function { Name: 'FunctionA' })
CREATE (f:Function { Name: 'FunctionB' })
CREATE (f:Function { Name: 'FunctionC' })
CREATE (f:Function { Name: 'FunctionZ' })
MATCH (f:Function),(l:Library) WHERE (f.Name = "FunctionA") AND (l.Name = "Library.lib") AND (l.Path = "amd64") CREATE f-[:included_in]->l
MATCH (f:Function),(l:Library) WHERE (f.Name = "FunctionB") AND (l.Name = "Library.lib") AND (l.Path = "amd64") CREATE f-[:included_in]->l
MATCH (f:Function),(l:Library) WHERE (f.Name = "FunctionC") AND (l.Name = "Library2.lib") AND (l.Path = "amd64") CREATE f-[:included_in]->l
MATCH (f:Function),(l:Library) WHERE (f.Name = "FunctionZ") AND (l.Name = "Library.lib") AND (l.Path = "i386") CREATE f-[:included_in]->l
MATCH (f:Function),(l:Library) WHERE (f.Name = "FunctionZ") AND (l.Name = "Library.lib") AND (l.Path = "amd64") CREATE f-[:included_in]->l
MATCH (f:Function),(t:Target) WHERE (f.Name = "FunctionA") AND (t.Name = "Target.exe") CREATE f-[:used_in]->t
MATCH (f:Function),(t:Target) WHERE (f.Name = "FunctionB") AND (t.Name = "Target.exe") CREATE f-[:used_in]->t
MATCH (f:Function),(t:Target) WHERE (f.Name = "FunctionC") AND (t.Name = "Target2.exe") CREATE f-[:used_in]->t
MATCH (f:Function),(t:Target) WHERE (f.Name = "FunctionZ") AND (t.Name = "Target3.exe") CREATE f-[:used_in]->t
MATCH (l:Library),(t:Target) WHERE (l.Name = "Library.lib") AND (l.Path ="amd64") AND (t.Name = "Target.exe") CREATE l-[:part_of]->t
MATCH (l:Library),(t:Target) WHERE (l.Name = "Library2.lib") AND (l.Path ="amd64") AND (t.Name = "Target2.exe") CREATE l-[:part_of]->t
MATCH (l:Library),(t:Target) WHERE (l.Name = "Library.lib") AND (l.Path ="i386") AND (t.Name = "Target3.exe") CREATE l-[:part_of]->t
对于那些感兴趣的人,这里是我根据Wes提供的Cypher查询使用的Neo4Client代码。
var query = graphClient.Cypher
.Match("(function:Function)-[:used_in]->(target:Target),(function:Function)-[:included_in]->(library:Library)")
.Where((Target target) => target.Name == sourceTarget.Name)
.AndWhere((Target target) => target.Path == sourceTarget.Path)
.AndWhere((Target target) => target.PEType == sourceTarget.PEType)
.AndWhere((Target target) => target.FileArch == sourceTarget.FileArch)
.AndWhere((Library library) => library.Name == sourceLibrary.Name)
.AndWhere((Library library) => library.Path == sourceLibrary.Path)
.AndWhere((Library library) => library.PEType == sourceLibrary.PEType)
.AndWhere((Library library) => library.FileArch == sourceLibrary.FileArch)
.Return((function) => new
{
Functions = function.CollectAs<Function>()
})
.Results
.Select(result => new FunctionCollection()
{
Collection = result.Functions.Select(a => a.Data).ToList()
});
答案 0 :(得分:1)
似乎太容易了,但它是否像这样简单?如果没有,请提供更多信息。
MATCH (function:Function)-[:used_in]->(target:Target),
(function:Function)-[:included_in]->(library:Library)
WHERE (target.Name = "target.exe")
RETURN function, library