web-dev-qa-db-ja.com

条件付き挿入に合体を使用して折りたたむ/展開する必要があるのはなぜですか?

条件付き挿入のこのパターンがどのように機能するかを理解しようとしています。

g.V()
  .hasLabel('person').has('name', 'John')
  .fold()
  .coalesce(
    __.unfold(),
    g.addV('person').property('name', 'John')
  ).next();

折り畳み/展開の目的は何ですか?これらが必要な理由と、これが機能しない理由:

g.V()
  .coalesce(
    __.hasLabel('person').has('name', 'John'),
    g.addV('person').property('name', 'John')
  ).next();

Fold-then-unfoldパターンは私には冗長に思えますが、上記では同じ結果は得られません。

10
cejast

次のことを行うだけで何が起こるかを考えてみましょう。

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().has('name','marko')
==>v[1]
gremlin> g.V().has('name','stephen')
gremlin> 

「マルコ」の場合は何かを返し、「スティーブン」の場合は返しません。 「スティーブン」の場合は、fold()がこのパターンで本当に重要になるため、注意が必要なケースです。そのトラバーサルが何も返さない場合、その後に追加するステップには、それらのステップでアクションをトリガーするためのTraverserが存在しません。したがって、次の場合でも頂点は追加されません。

gremlin> g.V().has('name','stephen').addV('person')
gremlin> 

しかし、fold()の場合はどうなるか、次のようになります。

gremlin> g.V().has('name','stephen').fold()
==>[]

fold()はバリアを減らすステップであるため、そのポイントまでのトラバーサルの内容が何も生成されない場合でも、そのポイントまでのトラバーサルを熱心に評価し、その内容をListとして返します。ご覧のとおり、空のリストが表示されます)。また、空のListがある場合、その空のListはトラバーサルを流れるTraverserであるため、将来のステップが実行されます。

gremlin> g.V().has('name','stephen').fold().addV('person')
==>v[13]

これが、例で「John」の存在をチェックしているためにfold()する理由を説明しています。彼が見つかった場合、彼はListに存在し、そのListが「John」がcoalesce()にヒットすると、最初のチェックはunfold()に「John」でListを送信し、Vertexを返します。 Listが空で、「John」が存在しないために何も返さない場合、頂点が追加されます(ちなみに、addV()の前に「g。」は必要ありません。 、それは匿名トラバーサルである必要があり、したがって__.addV('person'))です。

あなたの例に目を向けると、私はあなたがこれについて質問したいと思うことを最初に指摘します:

g.V().
  coalesce(
    __.has('person','name', 'John'),
    __.addV('person').property('name', 'John'))

これは完全に異なるクエリです。このトラバーサルでは、すべての頂点を反復し、各頂点に対してcoalesce()にあるものを実行すると言っています。 addV()constant('x')に置き換えると、これをかなりわかりやすく確認できます。

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().
......1>   coalesce(
......2>     has('person','name', 'John'),
......3>     constant('x'))
==>x
==>x
==>x
==>x
==>x
==>x
gremlin> g.V().
......1>   coalesce(
......2>     has('person','name', 'marko'),
......3>     constant('x'))
==>v[1]
==>x
==>x
==>x
==>x
==>x

ここで、addV()と「John」で何が起こるか想像してみてください。 addV()を6回呼び出します。頂点ごとに、「ジョン」ではない頂点に1回呼び出されます。

gremlin> g.V().
......1>   coalesce(
......2>     __.has('person','name', 'John'),
......3>     __.addV('person').property('name', 'John'))
==>v[13]
==>v[15]
==>v[17]
==>v[19]
==>v[21]
==>v[23]

個人的には、この種のロジックを Gremlin DSL でまとめるというアイデアが好きです-そうする良い例があります ここ

いい質問-「ElementExistence」の問題を、読むことができるグレムリンレシピの一部として説明しました ここ

15