Использование maxdepth и обход orientdb

Я использую orientdb v2.1.4 Можно ли выполнить обход orientdb из целевой записи с условием while и параметром maxdepth либо в SQL, либо в Java API? Например:

traverse all() from TargetRecordID maxdepth 25 while @class <> 'some_edge_class'

Похоже, что синтаксический анализатор orientdb применяет условие maxdepth и игнорирует условие while.

Я использую условие while, потому что всего у меня есть 10 различных классов краев, но я хочу выполнить обход, исключая подмножество (~3) классов краев. Если у вас есть альтернативный подход, который я использую для игнорирования определенных классов краев во время обхода, это тоже было бы здорово.


person kfresh    schedule 08.12.2015    source источник
comment
это похоже на ошибку, вы должны зарегистрировать проблему в официальном трекере проблем   -  person Luigi Dell'Aquila    schedule 09.12.2015
comment
Страница по адресу orientdb.com/docs/2.1/SQL-Traverse.html. указывает, что данный запрос синтаксически правильный, поэтому 2.1.7 (или, по крайней мере, версия, которую я использую) явно несовершенна. Обходной путь, который, похоже, работает, заключается в том, чтобы включить ограничение на $depth в условии WHILE (например, WHILE ... and $depth <= 25) вместо использования MAXDEPTH.   -  person peak    schedule 10.12.2015
comment
@LuigiD спасибо, сделаю   -  person kfresh    schedule 10.12.2015
comment
@peak Спасибо за отзыв. Я использовал предложенный вами подход, но недавно прочитал, что maxdepth быстрее, чем $depth, поэтому я хотел попробовать использовать maxdepth с условием while. И, как вы сказали, похоже, что это синтаксически правильно, поэтому я решил проверить, есть ли у кого-нибудь эта проблема.   -  person kfresh    schedule 10.12.2015
comment
@LuigiD Вот оно: github.com/orientechnologies/orientdb/issues/5445   -  person kfresh    schedule 10.12.2015
comment
Вот ссылка на выпуск OrientDB: github.com/orientechnologies/orientdb/issues/5445   -  person peak    schedule 10.12.2015
comment
@peak да, я только что сделал это   -  person kfresh    schedule 10.12.2015


Ответы (2)


попробуйте этот запрос:

traverse both() from YourClass while both('your_edge_class').size() = 0 and $depth <= 25

поэтому ход не будет проходить по вершинам, связанным с ребром/ребрами, которые вы указали

Редактировать:

Учитывая следующий пример графика и предполагая, что вам не нужны ребра type1 и type2, хотите ли вы, чтобы узлы 1,2,3,4,5 и 8 были соединены с ребром type 3, или вы хотите избежать всех вершины связаны также с type 1и type 2?

введите здесь описание изображения

Редактировать:

Вы можете использовать эту функцию javascript с тремя параметрами (rid, maxDepth, excludeEdges)

var g=orient.getGraph();
var result=[];
var current=[];
var next=[];
var listEdges=excludeEdges.substring(1,excludeEdges.length-1).split(",");
var root=g.command('sql','select from '+rid);
current.push(root[0]);
var step=1;
while(current.length>0 && step<=maxDepth){
    for(i=0;i<current.length;i++){
        getVertex(current[i],"OUT");
        getVertex(current[i],"IN");
    }
    change();
    step++;
}
return result;

function change(){
    current=[];
    for (index=0;index<next.length;index++)
        current.push(next[index]);
    next=[];
}

function getVertex(start,direction){
    var edgeDir="outE()";
    var reverseDirection="in";
    if(direction=="IN"){
        edgeDir="inE()";
        reverseDirection="out";
    }
    var edges=g.command("sql","select expand("+edgeDir +") from "+start.getId());
    for(h=0;h<edges.length;h++){
        var found=false;
        for(m=0;m<listEdges.length;m++){
            if(edges[h].getProperty("@class")==listEdges[m]){
                found=true;
                break;
            }
        }
        if(found==false){
            var vertex=g.command("sql","select expand("+ reverseDirection + ") from " +edges[h].getId());
            for(j=0;j<result.length;j++){
                if(result[j].getId().toString().equals(vertex[0].getId().toString()) ||
                    vertex[0].getId().toString().equals(rid)){
                    found=true;
                    break;
                }
            }
            if(found==false){
                result.push(vertex[0]);
                next.push(vertex[0]);
            }
        }
    }
}

Используя следующую команду

select expand(result) from (select myFunction("#9:1",25,"[type1,type2]") as result)
person LucaS    schedule 09.12.2015
comment
Привет, @LucaS, спасибо за отзыв. Итак, я понял, что сделал небольшую ошибку в своем вопросе. Я хочу перейти из определенной записи (я отредактирую это в своем вопросе). Итак, в вашем примере выше: предположим, что вершина 2 имеет RID #1:2. Я хочу выполнить обход на глубину 2 из #1:2, игнорируя ребра type1 и type2, поэтому возвращая вершины 1, 3, 5, 4. Как вы думаете, этот запрос поможет на графике в вашем примере? traverse both() from #1:2 while both('type1').size() = 0 and both('type2').size() = 0 and $depth <= 2 - person kfresh; 10.12.2015
comment
Привет, kfresh, этот запрос не будет работать, если условие не будет соблюдено с начального узла. Я нашел разные способы получения вершин, которые вы ищете. 1) Чтобы найти 1,3,4,5, вы можете использовать TRAVERSE с: select expand($a) from #1:2 let $a=(traverse both('type3') from (select in('type3') from $parent.$current) while both('type3').size() > 0 and $depth < 2 and name <> $current.name) order by name - person LucaS; 10.12.2015
comment
2) Без ТРАВЕРСА: select expand($a) as node from #1:2 let $a=(select from node where both('type3').size() > 0 and name <> $parent.current.name) unwind node - person LucaS; 10.12.2015
comment
Привет, kfresh, у тебя есть возможность попробовать запросы? - person LucaS; 11.12.2015
comment
Привет, LucaS, спасибо за варианты. Я не пробовал, но думаю, что понимаю, что вы в них делаете, и вижу, как они дадут желаемый результат. Но я не уверен, как переписать этот запрос (например, ваш первый вариант) для моего случая, когда у меня есть ~ 10 типов ребер, и я не хочу проходить 3 типа ребер, а глубина составляет ‹10. По крайней мере, с точки зрения написания запроса кажется, что это будет беспорядочно. ВДИТ? - person kfresh; 11.12.2015
comment
Привет, kfresh, я думаю, можно было бы решить вашу проблему с помощью функции javascript вместо запроса, не могли бы вы принять ее в качестве альтернативы? - person LucaS; 11.12.2015

С Java API

OrientGraph g=new OrientGraph("remote:localhost/yourDb");
Traverse traverse = new Traverse(g);

List<String> listExcludeEdges=new ArrayList<String>();
listExcludeEdges.add("type1");
listExcludeEdges.add("type2");
int maxDepth=3;
String id="#9:1";

Set<Vertex> vertex=traverse.get(id,maxDepth,listExcludeEdges);
for(Vertex v:vertex){
    System.out.println(v.getId());
}
g.shutdown();

Траверс класса

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;

public class Traverse {

    private Set<Vertex> listVertex = new LinkedHashSet<Vertex>(); 
    private OrientGraph g;
    private int maxDepth;
    private List<String> listExcludeEdges;
    private Vertex root;

    public Traverse(OrientGraph g) {
        this.g = g;
    }

    public Set<Vertex> get(String id,int maxDepth,List<String> listExcludeEdges) {
        this.maxDepth=maxDepth;
        this.listExcludeEdges=listExcludeEdges;
        if(checkClassOrRid(id)){
            if (getRoot(id)) 
                getChildren(1,this.root);
        }
        return this.listVertex;
    }

    private boolean checkClassOrRid(String id){
        Pattern pattern = Pattern.compile("^#[0-9]+:[0-9]+");
        Matcher matcher = pattern.matcher(id);
        if (matcher.matches()) {
            for (Vertex v : g.getVertices()) {
                if (v.getId().toString().equals(id))
                    return true;
            }   
        }
        return false;
    }

    protected boolean getRoot(String id) {      
        this.root =  g.getVertex(id);
        if(this.root!=null)
            return true;
        return false;
    }

    protected void getChildren(int step,Vertex from) {
        if(step<=maxDepth){
            getVertex(Direction.OUT,from,step);
            getVertex(Direction.IN,from,step);
        }
    }

    private void getVertex(Direction direction,Vertex from,int step){
        Iterable<Edge> edges = from.getEdges(direction);
        for(Edge e:edges){
            boolean found=false;
            for(String s:this.listExcludeEdges){
                if(e.getProperty("@class").equals(s))
                    found=true;
            }
            if(found==false){
                Vertex vertex=null;
                if(direction==Direction.OUT)
                    vertex=e.getVertex(Direction.IN);
                else
                    vertex=e.getVertex(Direction.OUT);
                this.listVertex.add(vertex);
                getChildren(step+1,vertex);
            }
        }
    }
}
person Alessandro Rota    schedule 10.12.2015