2016-07-05 4 views
2

ルートの頂点に来る方法を知っている部分グラフがあります。しかし、その後私はそれを歩く必要があります。Javaドライバを使用したDSEグラフ、グラフをどのように歩くか(ツリーのような)

具体的には、「サブグラフを歩いてください」ということは、サブグラフのすべての葉に歩いて行かなければならないということです(サブグラフはツリーのようなものだからです)。頂点。

私の質問は、どのように最もパフォーマンスの高い方法で達成するのですか?

私は2つのソリューションについて考えることができます。

まず、session.executeGraph("g.V().has('id','1')").one()ステートメントをたくさんグラフに入れて、すべての単一の頂点とエッジを取得し、それらの計算を行います。しかし、私はこの方法が非常に非効率だと思う。

または私は私は私はかなり確信しています

GraphNode node = session.executeGraph("g.V().has('id','1').repeat(outE().subgraph('sg').otherV()).cap('sg').path()").one(); 
Path path = node.asPath(); 

を得ることができますパスオブジェクトでは動作し、第二の溶液が好ましいですが、私はどのように歩くためにパスオブジェクトを使用する見当もつかない私が見ることができるのは、オブジェクトのフラットマップだけだからです。ここ

更新#1

は、例えば木の写真です。目標は、ノードAの「複合価値」が必要です。ルールは非常に単純です。ノード(ルートを除く)には値があります。エッジには重みがあります。私は重みに関するすべての値を合計しなければならない。子供が親を1人しか持たない限り、私は完全な価値を取ることができます。子供が複数の親を持っている場合、私は重み付けを考慮する必要があります。例えばツリーで、Bの合成値は 100 + (500 * 50/60) + 1000であろうとの合成値はcombined value of B plus value of C == 2156.67)であろう。したがって、頂点とエッジから計算のためのプロパティが必要です。

更新#2

ここに私の解決策があります。

実際の計算を行っている抽象的なTreeクラスを実装しました(モック実装もあるため)。

public abstract class Tree { 
    // String == item id 
    protected final Map<String, Item> items = new HashMap<>(); 
    private final String rootItemId; 

    protected Tree(String rootItemId) { 
     this.rootItemId = rootItemId; 
    } 

    public void accumulateExpenses() { 
     accumulateExpenses(null, null); 
    } 

    private double accumulateExpenses(String itemId, String parentItemId) { 
     final Item item = itemId == null ? items.get(rootItemId) : items.get(itemId); 
     final double expense = item.getExpense(); 
     double childExpenses = 0; 

     for (String childId : item.getChildIds()) { 
      childExpenses += accumulateExpenses(childId, item.getId()); 
     } 

     // calculate the percentage in case the item has multiple parents 
     final double percentage = item.getPercentage(parentItemId); 
     final double accumulatedExpenses = percentage * (expense + childExpenses); 
     item.setAccumulatedExpense(accumulatedExpenses); 

     return accumulatedExpenses; 
    } 
} 

そして、スーパークラス(抽象的なツリー)のアイテムマップを埋め込むGraphTreeクラスを実装しました。

public class GraphTree extends Tree { 
    public GraphTree(GraphNode graphNode, String rootNodeId) { 
     super(rootNodeId); 

     final GraphNode vertices = graphNode.get("vertices"); 
     final GraphNode edges = graphNode.get("edges"); 

     for (int i = 0; i < vertices.size(); i++) { 
      final Vertex vertex = vertices.get(i).asVertex(); 
      final Item item = Item.fromVertex(vertex); 
      super.items.put(item.getId(), item); 
     } 

     for (int i = 0; i < edges.size(); i++) { 
      final Edge edge = edges.get(i).asEdge(); 
      final Relation relation = Relation.fromEdge(edge); 
      super.items.get(relation.getParentId()).getRelations().add(relation); 
     } 
    } 
} 

完全性のために、ここではItemクラスもあります。

public class Item { 
    private String id; 
    private double accumulatedExpense; 
    private final List<Relation> relations = new ArrayList<>(); 
    private final Map<String, Expense> expenses = new HashMap<>(); 

    public void setAccumulatedExpense(double accumulatedExpense) { 
     this.accumulatedExpense = accumulatedExpense; 
    } 

    public double getPercentage(String parentId) { 
     if (parentId == null) { 
      return 1; 
     } 

     double totalWeight = 1; 
     double weight = 1; 

     for (Relation relation : relations) { 
      if (Objects.equals(id, relation.getChildId())) { 
       totalWeight += relation.getWeight(); 
       if (Objects.equals(parentId, relation.getParentId())) { 
        weight = relation.getWeight(); 
       } 
      } 
     } 

     return weight/totalWeight; 
    } 

    public static Item fromVertex(Vertex vertex) { 
     final Item item = new Item(); 
     item.setId(IdGenerator.generate(vertex)); 

     return item; 
    } 

    public List<String> getChildIds() { 
     return relations.parallelStream() 
        .filter(relation -> Objects.equals(relation.getParentId(),id)) 
        .map(Relation::getChildId) 
        .collect(Collectors.toList()); 
    } 
} 

最初のサブグラフを取得するには、次のコードを使用しました。

final String statement = String.format("g.V('%s').repeat(outE().subgraph('sg').otherV()).cap('sg')", rootNodeId); 
    final GraphNode node = session.executeGraph(statement).one(); 
+0

あなたは幅優先探索を行っていると考えることがありますか? [This](http://stackoverflow.com/a/17833088/1457059)はかなり気の利いたアプローチを示しています。 gremlinクエリをDSEグラフに渡すのは簡単です。 –

+0

ありがとうございます。しかし、私が持っている問題は、グラフを取得する方法(2番目のクエリでうまくいく)ではなく、Javaドライバでどのように動作するかです。私が戻すのは、すべての頂点とエッジを含む平坦な 'Map'を持つ' GraphNode'です。だから私は頂点間の重要な関係をすべて失う。私が期待したのは、 'node.getOutEdges()。forEach(edge-> edge.getInVertices())'などのようなものです。だから私の主な問題は、Java Driverを適切に扱う方法です。私はグレムリンについてはかなり新しいですが、これまでのところ理解していると思いますが、期待通りにJavaに転送することはできません。 –

+0

あなたが探している究極の結果は何ですか?パスが必要なのではなく、特定のプロパティだけが蓄積されるように思えます。 –

答えて

2

コメントを何度も読んだ後でも、1つのクエリを使用して解決策を見つけようとすると、私は論理に惑わされます。あなたがこれを行うことができ、あなただけの特定の情報(例えば、頂点のvalue財産とエッジのweightプロパティ)を必要とする場合

g.V().has('id','1').repeat(outE().as("e").inV()).emit(__.not(outE())).tree() 

:したがって、それはどれだけのツリー表現を取得する方法を教えておそらく最善です

g.V().has('id','1'). 
    repeat(outE().as("e").inV()).emit(__.not(outE())). 
    tree().by("value").by("weight") 

と頂点Aので、あなたが​​3210ステップを追加する必要があります、value性質を持っていないようです:

g.V().has('id','1'). 
    repeat(outE().as("e").inV()).emit(__.not(outE())). 
    tree().by(coalesce(values("value"), constant(0))).by("weight") 

私は後でもう一度サンプルグラフでプレーする必要がある場合には

UPDATEは、ここでそれを作成するためのコードです。

g = TinkerGraph.open().traversal() 
g.addV().property(id, "A").as("a"). 
    addV().property(id, "B").property("value", 100).as("b"). 
    addV().property(id, "C").property("value", 200).as("c"). 
    addV().property(id, "D").property("value", 500).as("d"). 
    addV().property(id, "E").property("value", 1000).as("e"). 
    addV().property(id, "Z").property("value", 900).as("z"). 
    addE("link").from("a").to("b").property("weight", 80). 
    addE("link").from("a").to("c").property("weight", 20). 
    addE("link").from("b").to("d").property("weight", 50). 
    addE("link").from("b").to("e").property("weight", 40). 
    addE("link").from("z").to("d").property("weight", 10).iterate() 
+0

私は悲しいです、私は私の問題をより良い方法で記述することはできません。しかし、あなたは、私がすでに問題を1つ以上の厄介なgremlinステートメントだけで解決できると思うという意味で私をすでに助けてくれました。だから、私はグレムリンについてもっと深く掘り下げなければなりません。あなたの発言を出発点として使用します。ありがとう!たぶんもう1つの質問が私には役に立ちます... gremlinやJavaの問題を解決すべきだと思いますか? –

+0

GroovyまたはJavaを意味しますか?あなた次第では、私は個人的にJavaを使うことを好みます。 –

+0

gremlinでの計算(ツリートラバーサルを含む)を行うべきか、またはサブグラフを読み込んでJavaで計算を行うだけでいいですか? –

関連する問題