我有这个数据库:
客户=>事件=>文件=>文件名
客户有一个ID 事件有一个ID和一个reportOn属性 文件具有ID和fileSize,mimeType,恶意软件属性 文件名具有ID 客户端对事件有外发的Edge(已报告),事件对文件有外发的Edge(containsFile),文件有对文件名的外发Edge(hasName)。
以下是一些示例数据:
g.addV('client').property('id','1').as('1').
addV('incident').property('id','11').property('reportedON', '2/15/2019 8:01:19 AM').as('11').
addV('file').property('id','100').property('fileSize', '432534').as('100').
addV('fileName').property('id','file.pdf').as('file.pdf').
addE('reported').from('1').to('11').
addE('containsFile').from('11').to('100').
addE('hasName').from('100').to('file.pdf').iterate()
在下面的C#代码中,我正在检查数据库中的每个fileName是否存在特殊的文件扩展名。之后,我使用具有这些特殊文件扩展名的fileName来获取它们的所有值以及它们周围的顶点以及它们在第二个查询中的值(位于foreachloop中):
var resultSet = await SubmitQueryAsync("g.V().hasLabel('fileName')");
if (resultSet.Length > 0)
{
foreach (var result in resultSet)
{
JObject jsonData = result;
string fileId = jsonData["Id"].Value<string>();
string fileExtension = "";
string[] fileExtensions = { ".ace", ".arj", ".iso", ".rar", ".gz", ".acrj", ".lnk", ".z", ".tar", ".xz" };
HashSet<string> hSet = new HashSet<string>(fileExtensions);
if (fileId.Contains("."))
{
fileExtension = fileId.Substring(fileId.LastIndexOf('.'));
}
if (hSet.Contains(fileExtension))
{
var resultSet2 = await SubmitQueryAsync("g.V().has(id, '" + fileId + "').as('FILENAME').in('hasName').as('FILE').in('containsFile').as('INCIDENT').select('FILE').valueMap().as('FILEVALUES').select('INCIDENT').valueMap().as('INCIDENTVALUES').select('FILE', 'FILEVALUES', 'FILENAME', 'INCIDENTVALUES')");
list = FillList(list, resultSet2);
}
}
}
因此,对于具有特殊文件扩展名之一的每个fileName,我都在foreachloop中执行一个查询。问题是这对于数据库来说查询太多了。那么我怎样才能使它更有效率呢?
答案 0 :(得分:0)
您可能需要做的第一件事是更改数据模型,并在“ fileName”上包含“ ext”(即“ fileExtension”)属性,以便您可以轻松地对其进行搜索(我不认为CosmosDB支持{ {1}}或类似的文本搜索选项),因此:
TextP
然后,将所有C#滚动到单个Gremlin遍历中非常简单:
g.addV('client').property('id','1').as('1').
addV('incident').property('id','11').property('reportedON', '2/15/2019 8:01:19 AM').as('11').
addV('file').property('id','100').property('fileSize', '432534').as('100').
addV('fileName').property('id','file.pdf').property('ext','.pdf').as('file.pdf').
addE('reported').from('1').to('11').
addE('containsFile').from('11').to('100').
addE('hasName').from('100').to('file.pdf').iterate()
请注意,我在您的“扩展名”列表中添加了“ .pdf”,以便根据您的示例数据返回结果。除此之外,我认为您的查询确实比它应该的更为复杂-让我们尝试简化一下,因为所有步骤标签都使此操作难以进行。我更喜欢使用gremlin> g.V().has('fileName','ext',within(".ace", ".arj", ".iso", ".rar", ".gz", ".acrj", ".lnk", ".z", ".tar", ".xz", ".pdf")).as('FILENAME').
......1> in('hasName').as('FILE').
......2> in('containsFile').as('INCIDENT').
......3> select('FILE').valueMap().as('FILEVALUES').
......4> select('INCIDENT').valueMap().as('INCIDENTVALUES').
......5> select('FILE', 'FILEVALUES', 'FILENAME', 'INCIDENTVALUES')
==>[FILE:v[5],FILEVALUES:[fileSize:[432534],id:[100]],FILENAME:v[8],INCIDENTVALUES:[reportedON:[2/15/2019 8:01:19 AM],id:[11]]]
:
project()
这使我认识到“ FILE”和“ FILEVALUES”基本上是相同的东西,可以组合:
gremlin> g.V().has('fileName','ext',within(".ace", ".arj", ".iso", ".rar", ".gz", ".acrj", ".lnk", ".z", ".tar", ".xz", ".pdf")).
......1> project('FILE','FILEVALUES','FILENAME','INCIDENTVALUES').
......2> by(__.in('hasName')).
......3> by(__.in('hasName').valueMap()).
......4> by().
......5> by(__.in('hasName').in('containsFile').valueMap())
==>[FILE:v[5],FILEVALUES:[fileSize:[432534],id:[100]],FILENAME:v[8],INCIDENTVALUES:[reportedON:[2/15/2019 8:01:19 AM],id:[11]]]
我不喜欢我们两次遍历gremlin> g.V().has('fileName','ext',within(".ace", ".arj", ".iso", ".rar", ".gz", ".acrj", ".lnk", ".z", ".tar", ".xz", ".pdf")).
......1> project('FILEVALUES','FILENAME','INCIDENTVALUES').
......2> by(__.in('hasName').valueMap(true)).
......3> by().
......4> by(__.in('hasName').in('containsFile').valueMap())
==>[FILEVALUES:[id:5,fileSize:[432534],id:[100],label:file],FILENAME:v[8],INCIDENTVALUES:[reportedON:[2/15/2019 8:01:19 AM],id:[11]]]
,所以:
in('hasName')
但这会稍微改变返回结果的结构。我想可以通过更多转换将其恢复到原来的水平,但是我不确定您是否对此感到担心。现在,我只是想帮助使查询更具可读性。