我在Python 3.4中使用了ArangoDb v3.0.7。arangosh vs arango中的ArangoDB圖形遍歷結果之間的區別http
我在arango shell和通過使用'POST/_api/traversal'(從python使用python-arango庫)調用遍歷器中運行圖遍歷。我爲兩個呼叫使用相同的參數/配置,並使用相同的用戶定義擴展器和訪問者功能。
雖然shell中的遍歷按預期工作,但通過http api調用的遍歷不會返回應該訪問的所有頂點,如由expander函數指定的。
在蟒/ HTTP側,我執行:
query_result = dl_graph.traverse(
start_vertex=start_vertex,
strategy="dfs",
max_depth=8,
order="preorder",
vertex_uniqueness="global",
edge_uniqueness="global",
filter_func=None,
expander_func=expander, // string containing function body, see def below
visitor_func=visitor // string containing function body, see def below
)
當阿朗戈殼下運行,則配置是:
{
"datasource" : {
"graph" : [ Graph kraken EdgeDefinitions: [
"Owns: [Account] -> [Account, Building]",
"Services: [BSObject] -> [BSObject, SpatialObject]",
"Employs: [Account] -> [Account, User]",
"WorksIn: [Project, Role, Team, TeamMember, User] -> [Building, Project, SpatialO...",
"IsIn: [SpatialObject] -> [Building, SpatialObject]",
"AccessControl: [Project, Role, Team, TeamMember, User] -> [BSObject, Building, C...",
"Instantiation: [BSObject] -> [Class]",
"Supply: [BSObject] -> [BSObject, SpatialObject]",
"HasRole: [TeamMember, User] -> [Role]",
"Contracts: [Account] -> [Account, Contract, Service]",
"can_read: [Team] -> [message_exchange]",
"can_write: [Team] -> [message_exchange]",
"Context: [message_exchange] -> [BSObject, Building, SpatialObject]",
"has_authority_over: [Team] -> [Team]",
"Provides: [Contract, ContractSchedule, Role] -> [Service]",
"To: [Service] -> [Team]",
"Under: [Role] -> [Contract, ContractSchedule]",
"Leases: [Account] -> [Building, SpatialObject]",
"Partof: [ContractSchedule] -> [Contract]",
"Manages: [testA] -> [Account]"
] VertexCollections: [
"Contract",
"ContractSchedule",
"Group",
"Service",
"test1",
"testdialog",
"GraphViews",
"GraphViewPositions",
"testBuilding",
"test5",
"test6",
"test7",
"test10",
"test11",
"test123",
"test134567",
"testA"
] ],
"getVertexId" : function (vertex) { ... },
"getPeerVertex" : function (edge, vertex) { ... },
"getInVertex" : function (edge) { ... },
"getOutVertex" : function (edge) { ... },
"getEdgeId" : function (edge) { ... },
"getEdgeFrom" : function (edge) { ... },
"getEdgeTo" : function (edge) { ... },
"getLabel" : function (edge) { ... },
"getAllEdges" : function (vertex) { ... },
"getInEdges" : function (vertex) { ... },
"getOutEdges" : function (vertex) { ... }
},
"order" : 0,
"itemOrder" : 0,
"strategy" : 1,
"uniqueness" : {
"vertices" : 2,
"edges" : 2
},
"visitor" : function (config, result, vertex, path, connected) { ... },
"filter" : function maxDepthFilter (config, vertex, path) { ... },
"expander" : function (config, vertex, path) { ... },
"maxIterations" : 10000000,
"minDepth" : 0,
"maxDepth" : 8,
"buildVertices" : true,
"messages" : [
"in edge, gedID:525147be-ebec-11e5-9e42-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:525147be-ebec-11e5-9e42-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:525147be-ebec-11e5-9e42-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:525147be-ebec-11e5-9e42-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:525147be-ebec-11e5-9e42-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca",
"in edge, gedID:cfa4fa2e-ef0e-11e5-8377-80193436fdca"
]
}
注意 '消息' 陣列最後是由下面的擴展函數添加的。這是我嘗試在http api下運行時將某些診斷輸出返回給python客戶端。這種技術也只能在shell下運行。設置消息數組的原因是,當使用http api時,我找不到'require(「internal」)。print(...)'輸出的位置。
擴展器功能如下。關鍵部分是該函數將遍歷圖形,直到它到達gedID爲'30dd37a6-ec18-11e5-81b7-80193436fdca'的頂點。當訪問者函數接收到這個頂點時,它會創建一個從該頂點到該路徑的ID列表。
function (config, vertex, path) {
if (!config.messages) config.messages = [];
var connections = [ ];
if (vertex.gedID == '67a59b76-efc3-11e5-9c6f-80193436fdca'
|| vertex.gedID == '2df65d4a-ef3f-11e5-b2f8-80193436fdca'
|| vertex.gedID == 'eb529db8-453e-11e6-b430-80193436fdca'
|| vertex.gedID == 'd38d7148-5ccd-11e6-b863-80193436fdca'
|| vertex.gedID == 'e6dc9d00-5ccd-11e6-9362-80193436fdca') // follow out edges for these vertices only
{
config.datasource.getOutEdges(vertex).forEach(function (e) {
require("internal").print("vertex, name:" + vertex.name);
require("internal").print("out edge, gedID:" + e.gedID);
var toVertex = require("internal").db._document(e._to)
if (toVertex.gedID != 'c1da8df6-2731-11e6-9aba-80193436fdca' // Block traversal through this vertex
&& (e.gedID != '525147be-ebec-11e5-9e42-80193436fdca' || e.Update == 'afd34490-ef35-11e5-b18e-80193436fdca') // not equal to edges of this type, and update has the specified value
&& !(vertex.gedID == '67a59b76-efc3-11e5-9c6f-80193436fdca' && toVertex.gedID == '67a59b76-efc3-11e5-9c6f-80193436fdca')) // ignore connections between vertices of this type
connections.push({vertex: toVertex, edge: e});
});
}
else
{
config.datasource.getInEdges(vertex).forEach(function (e) {
require("internal").print("vertex, name:" + vertex.name);
require("internal").print("in edge, gedID:" + e.gedID);
config.messages.push("in edge, gedID:" + e.gedID);
if (vertex.gedID != "30dd37a6-ec18-11e5-81b7-80193436fdca" // Terminating vertex
&& e.gedID != '1605c270-269e-11e6-9b64-80193436fdca' // Avoid traversal in this direction
&& e.gedID != 'a50f19d8-efdc-11e5-a5bf-80193436fdca' // Avoid traversal in this direction
&& e.gedID != '8e327408-5e45-11e6-8c9a-80193436fdca') // Avoid traversal in this direction
connections.push({ vertex: require("internal").db._document(e._from), edge: e});
});
require("internal").print("messages:" + config.messages);
}
return connections;
}
訪問者函數爲:
function (config, result, vertex, path, connected) {
if (! result || ! result.visited) {
return;
}
require("internal").print("messages:" + config.messages);
if (!result.visited.pathVertices) {result.visited.pathVertices = []}
result.visited.messages = config.messages;
if (result.visited.vertices) {
result.visited.vertices.push(vertex);
}
if (result.visited.paths) {
if (vertex.gedID == "30dd37a6-ec18-11e5-81b7-80193436fdca")
{
for (var e = 0; e < path.edges.length; e++)
{
result.visited.paths.push(path.edges[e]._id)
}
for (var v = 0; v < path.vertices.length; v++)
{
result.visited.pathVertices.push(path.vertices[v]._id)
}
}
}
}
的目的是,當用id「30dd37a6-ec18-11e5-81b7-80193436fdca」頂點被找到時,pathVertices陣列填充了標識。
當在arango shell下運行時,最終的頂點('30dd37a6-ec18-11e5-81b7-80193436fdca')被傳遞給visitor函數,並且pathVertices數組被填充。但是,通過http api運行時,pathVertices數組返回爲空。
此外,'result.visited.vertices'數組包含在shell下運行時的最終頂點(30dd37a6-ec18-11e5-81b7-80193436fdca),但在使用http api運行時缺少此頂點。
有可能有更好的方法來做到這一點,我很歡迎這方面的投入,但這裏的關鍵問題是爲什麼arango shell和http api之間的遍歷方式有所不同(以及我能否將我缺少的vertex/pathVertices數組返回給python代碼)。
Definitly to much code! [如何創建一個最小,完整和可驗證的示例](http://stackoverflow.com/help/mcve) – buhtz
抱歉,但通常當我閱讀其他人的問題時,會要求他們輸入更多代碼,特別是配置。這也是重現問題所需的代碼。 – Phil
我相信你可以讓它更小。 – buhtz