基于多个顶点遍历

时间:2015-12-03 06:35:59

标签: graph orientdb graph-traversal

我在OrientDB中有一个顶点为Area&的图形。边Place的{​​{1}}。您的平均路径为visited,依此类推。它跟踪用户在上一个之后访问过的位置。 Area > visited > Place > visited > Place > visited > Place > visited > Place包含YYYYmmDD visited

我试图在某一天基于任意datestamp个顶点找出所有Area个顶点 - 也就是说我想知道用户在首先访问某个地方之后到达某个地方的区域。

从路径中的任何一个Place遍历都很容易,但我需要遵循仅针对特定Place的路径。我所做的是我为datestamp创建了索引以快速获得一天的datestamp边缘,然后找到visited到第一个in的边缘。但是现在我无法弄清楚如何基于第一个Place创建查找所有Area个顶点的快速查询,同时还要确保该路径包含第二个Place。我可以通过Place在第一个和第二个Place之间获得路径,但我仍然遇到将路径扩展到包含shortestPath()个顶点的问题。

我找到了一些关于这个主题的理论,但是如果有人能指出我正确的方向如何使用OrientDB而不是纯图理论我真的很感激 - 我过去一周一直在研究这个问题。最初这是通过遍历所有内容然后进行选择而通过暴力来完成的,但随着数据库的增长,它显然不可持续。

3 个答案:

答案 0 :(得分:0)

修改

试试这个有三个参数的JavaScript函数(places,date,propertyPlace)

var g=orient.getGraph();
var myPlaces=places.substring(1,places.length-1).split(",");
var b=g.command("sql","select from Area");
var result=[];
if(checkPlaces){
    for(i=0;i<b.length;i++){
        var listPlaces=[];
        for(ind=0;ind<myPlaces.length;ind++){
            listPlaces.push(myPlaces[ind]);
        }
        if(search(b[i],listPlaces)){
            result.push(b[i]);
        }
    }
}
return result;

function checkPlaces() {
    for(index=0;index<myPlaces.length;index++){
        var place=g.command("sql","select from Place where "+ propertyPlace + "='"+myPlaces[index]+"'");
        if(place.length==0){
            return false;
        }
    }
    return true;
}

function checkDate(edge){
  var datestamp=edge.getRecord().field("datestamp");
  var year=datestamp.getYear()+1900;
  var month=datestamp.getMonth()+1;
  var day=datestamp.getDate();
  var app=date.split("-");
  var myYear=parseInt(app[0]);
  var myMonth=parseInt(app[1]);
  var myDay=parseInt(app[2]);
  if(year==myYear && month==myMonth && day==myDay){
    return true;
  }
  return false;
}


function search(v,places){
    var edge=v.getRecord().field("out_visited"); 
    if(edge!=null){
        var edgeIterator=edge.iterator();
        while(edgeIterator.hasNext()){
            var edge = edgeIterator.next();
            if (checkDate(edge)) {
                var v1 = edge.field("in");
                if(v1!=null){
                    var name = v1.field(propertyPlace);
                    for(j=0;j<places.length;j++){
                        if(name==(places[j])) {
                            places.splice(j, 1);
                            break;
                        }   
                    }
                    if(places.length==0){ 
                        return true;
                    }
                    else if(search(v1,places)){
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

使用以下命令

select expand(result) from (select myFunction("[place1,place2]","2015-12-03","name") as result)

让我知道它是否有效

答案 1 :(得分:0)

我创建了三个顶点'区域','位置'和'用户'以及两个边'已访问'和'放置',其中日期戳是边缘'访问过的属性。 通过这种方式,您不必每次将User作为边缘属性插入。

enter image description here

答案 2 :(得分:0)

这不是解决这个确切问题的方法,而是我提出的解决方法。灵感来自Orientdb get last vertex from each path when Traversing by edge property

我改为结构,以便现在为每次访问创建Area而不是静态,它还包括yyyymmdd时间戳。现在,我可以使用Area启动查询,并使用visited边缘仅在特定日期获取Place个顶点。

以下是查询:

SELECT $path, $depth FROM (
    TRAVERSE * FROM (
        SELECT outE('visited') FROM (
            SELECT EXPAND(rid) FROM INDEX:area.dt WHERE key = 20151205
        )
    ) WHILE (@class = 'visited' AND dt = 20151205) OR @class = 'place') 
WHERE @class = 'place' AND NOT (outE() contains (dt=20151205))

这将返回带有顶点和边的正确路径,因此您只能在某一天验证它。但请注意,Area未包含在路径中,我仍然需要弄清楚如何执行此操作但是如果您愿意,您可以在路径中向后遍历第一个visited边缘并将其设置为方式。