ArangoDB如何使用AQL将所有邻居与fulldepth匹配?

时间:2017-11-10 06:50:30

标签: graph arangodb nearest-neighbor aql

我们的ArangoDB v3.2中有~300k文档和~3m边缘 只要邻居的费率>我想得到起始文件和邻居的邻居的所有邻居。 0.5 ..它会给我社区有率> 0.5与开始文档相关。

现在我正在处理多个请求,但数据和项目将变得更大,我需要更好的性能,所以我需要一个AQL查询来通过一个请求获得所有neigbours ..

我试图让邻居深度为1..10所以它会得到所有的邻居,但它非常慢,所以我不能给出绝对的深度..

for vertex, edge, path in 1..10 any 'docs/10' doc_relations
    filter edge.rate > 0.5
return distinct edge

我需要像while循环这样的东西,但是没有像这样的查询函数。

2 个答案:

答案 0 :(得分:2)

我找到了答案。 我用User Functions扩展了arango。 您可以在将其添加到arango之后使用javascript编写任何函数,您可以在aql 上使用它。您也可以在js中使用任何aql查询。我写了一个js并将它添加到arangosh

要添加用户功能,请将其写入并保存,文件具有扩展名" .js"

让我们说例如我们将js函数保存到 path / to / func / file.js

首先选择一个数据库来添加新的用户功能

db._useDatabase("dbName");

您可以像这样添加

require("@arangodb/aql/functions").register("MYFUNCNAMESPACE::SEARCHRELATEDCLIPS",   require("path/to/func/file.js"), false);

注意:为将来的版本添加了第3个参数,它不适用于v3.2

您可以像这样取消注册

require("@arangodb/aql/functions").unregister("MYFUNCNAMESPACE::SEARCHRELATEDCLIPS");

path / to / func / file.js中的邻居搜索功能



function searchRelatedDocs( docID )
{
	var db = require("@arangodb").db;
	var groupDocs = [];
	var unSearchedDocs = [docID];
	var searchedDocs = {};
	var stepCounter = 0;
	var searchedDocCounter = 0;
	var start = new Number(new Date());
	var edgeSearchTime = 0;
	while( unSearchedDocs.length > 0 )
	{
		searchedDocCounter++;
		var docID = unSearchedDocs.shift();
		groupDocs.push(docID);
		
		searchedDocs[docID] = true;
		var startE = new Number(new Date());
		var docEdges = db.doc_relations.edges( docID );
		edgeSearchTime += ( new Number(new Date()) - startE );
		if( docEdges == null || docEdges == undefined || !( docEdges instanceof Array && docEdges.length != 0) )
			continue;
		
		for( var i = 0; i < docEdges.length; i++ )
		{
			stepCounter++;
			var edge = docEdges[i];
			
			
			if( edge.rate > 0.5 )
			{
				var relatedDocID = undefined;
			
				if( edge._to == docID )
				{
					relatedDocID = edge._from;
				}
				else
					relatedDocID = edge._to;
				
				if( searchedDocs[relatedDocID] == undefined )
				{
					searchedDocs[relatedDocID] = false;
					unSearchedDocs.push(relatedDocID);
				}
			}
			
			
		}
			
		
	}
	var end = new Number(new Date());
	
	var result = {};
	result.time = ( end - start );
	result.searchedDocs = searchedDocCounter;
	result.searchedEdges = stepCounter;
	result.edgeSearchTime = edgeSearchTime;
	var documents = db.docs.documents(groupDocs);
	
	if( documents != undefined && documents != null && documents.documents != undefined && documents.documents instanceof Array )
		result.vertices = documents.documents;
	
	return result;
}


module.exports = searchRelatedDocs;
&#13;
&#13;
&#13;

  

不要忘记在file.js中添加 module.exports = funcName;

答案 1 :(得分:1)

在我看来,您应该能够使用AQL实现您想要的效果。

微调AQL查询

看起来您可以微调定义AQL查询。具体来说,我建议沿着以下几行使用AQL查询:

for vertex, edge, path in 1..100000 OUTBOUND 'docs/10' doc_relations
   OPTIONS {uniqueVertices: "global", bfs: true }
   FILTER path.edges[*].rate ALL > 0.5
   return vertex

那是:

  • 如果可能,请使用OUTBOUND而不是ALL;
  • 如图所示使用OPTIONS,因为您不关心允许的顶点有多少可容许的路径;
  • 您的要求似乎对每个边缘沿着允许的“邻居”路径施加“费率&gt; 0.5”限制,因此ALL;
  • 既然你想要顶点,只需返回vertex;由于上述DISTINCT
  • ,因此无需OPTIONS

在.rate

上添加“跳过列表索引”

缓存数据库中的邻居

  

我需要AQL查询才能通过一个请求获取所有neigbours

就性能而言,这里显然存在时间/空间权衡,预先计算所有顶点的邻居或根据需要计算和缓存它们可能是有意义的。