Azure / azure-cosmos-dotnet-v2

Contains samples and utilities relating to the Azure Cosmos DB .NET SDK
MIT License
577 stars 837 forks source link

[Graph] Gremlin Query Compilation Error: Failed to interpret string "Microsoft.Azure.Graphs.GraphTraversal" into any data type. #496

Open BenjaBobs opened 6 years ago

BenjaBobs commented 6 years ago

I'm trying to first gather up some information about whether the entities I want to do operations on exist and have the correct labels and such, and then save them and reuse them so as to save bandwidth. I made a small sample here with the issue I'm running in to.

Setup:

g.V().hasLabel('tester').drop()
g.addV('tester').property('id', '1')
g.addV('tester').property('id', '2')
g.addV('tester').property('id', '3')

I then want to add edges from '1' to '2' and '3' if they all exist and the edges do not already exist.

Query 1:

g.inject(0)
 .sideEffect(coalesce(__.V('1').store('entityToUpdate'), constant('not_exist_1').store('errors')))
 .sideEffect(coalesce(__.V('2').store('otherEntity'), constant('not_exist_2').store('errors')))
 .sideEffect(coalesce(__.V('3').store('thirdEntity'), constant('not_exist_3').store('errors')))
 .project('errors', 'result')
 .by(select('errors'))
 .by(
  choose(
    select('errors').unfold(),
    constant([]),
    select('entityToUpdate').unfold()
      .sideEffect(coalesce(outE().inV().has('id', select('otherEntity').unfold().id()), addE('relation').to(select('otherEntity').unfold())).store('result'))
      .sideEffect(coalesce(outE().inV().has('id', select('thirdEntity').unfold().id()), addE('relation').to(select('thirdEntity').unfold())).store('result'))
      .sideEffect(project('edgeCount').by(outE().count()).store('result'))
    .select('result')
  )
 )

I store my entities as entityToUpdate, otherEntity and thirdEntity, and then reuse them both when checking if the edges already exist and when adding edges.

Result:

{
    "errors": [],
    "result": [
        {
            "id": "64ea0c23-206d-4680-b0de-2d747c6c1b3e",
            "label": "relation",
            "type": "edge",
            "inVLabel": "tester",
            "outVLabel": "tester",
            "inV": "2",
            "outV": "1"
        },
        {
            "id": "2",
            "label": "tester",
            "type": "vertex"
        },
        {
            "edgeCount": 1
        }
    ]
}

The part checking if the edge already exists (outE().inV().has('id', select('thirdEntity').unfold().id()) does not seem to compare the correct ids. I then tried another method.

Query 2:

g.inject(0)
 .sideEffect(coalesce(__.V('1').store('entityToUpdate'), constant('not_exist_1').store('errors')))
 .sideEffect(coalesce(__.V('2').store('otherEntity'), constant('not_exist_2').store('errors')))
 .sideEffect(coalesce(__.V('3').store('thirdEntity'), constant('not_exist_3').store('errors')))
 .project('errors', 'result')
 .by(select('errors'))
 .by(
  choose(
    select('errors').unfold(),
    constant([]),
    select('entityToUpdate').unfold()
      .sideEffect(coalesce(outE().inV().id().is(select('otherEntity').unfold().id()), addE('relation').to(select('otherEntity').unfold())).store('result'))
      .sideEffect(coalesce(outE().inV().id().is(select('thirdEntity').unfold().id()), addE('relation').to(select('thirdEntity').unfold())).store('result'))
      .sideEffect(project('edgeCount').by(outE().count()).store('result'))
    .select('result')
  )
 )

I'm not sure why, but this yields an exception.

Result:

"ClassName": "Microsoft.Azure.Graphs.Common.GraphCompileException",
"Message": "Gremlin Query Compilation Error: Failed to interpret string \"Microsoft.Azure.Graphs.GraphTraversal\" into any data type.",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": "   at Microsoft.Azure.Graphs.Runtime.WValueExpression.CompileToFunction(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WBooleanComparisonExpression.CompileToFunction(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WBooleanExpression.CompileToBatchFunction(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.CheckRemainingPredicatesAndAppendFilterOp(QueryCompilationContext context, GraphCommand graphCommand, HashSet`1 tableReferences, List`1 remainingPredicatesAndTheirTableReferences, List`1 childrenProcessor)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.ConstructOperator(GraphCommand graphCommand, MatchGraph graphPattern, QueryCompilationContext context, List`1 nonVertexTableReferences, List`1 predicatesAccessedTableReferences)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WCoalesceTableReference.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.ConstructOperator(GraphCommand graphCommand, MatchGraph graphPattern, QueryCompilationContext context, List`1 nonVertexTableReferences, List`1 predicatesAccessedTableReferences)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSideEffectTableReference.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.ConstructOperator(GraphCommand graphCommand, MatchGraph graphPattern, QueryCompilationContext context, List`1 nonVertexTableReferences, List`1 predicatesAccessedTableReferences)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WChooseTableReference.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.ConstructOperator(GraphCommand graphCommand, MatchGraph graphPattern, QueryCompilationContext context, List`1 nonVertexTableReferences, List`1 predicatesAccessedTableReferences)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WScalarSubquery.CompileToFunction(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WProjectTableReference.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.ConstructOperator(GraphCommand graphCommand, MatchGraph graphPattern, QueryCompilationContext context, List`1 nonVertexTableReferences, List`1 predicatesAccessedTableReferences)\r\n   at Microsoft.Azure.Graphs.Runtime.WSelectQueryBlock.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.Runtime.WSqlBatch.Compile(QueryCompilationContext context, GraphCommand graphCommand)\r\n   at Microsoft.Azure.Graphs.GraphTraversal.BuildPhysicalPlan(WSqlScript logicalPlan)\r\n   at Microsoft.Azure.Graphs.GraphTraversal.GetEnumerator()\r\n   at Microsoft.Azure.Graphs.GremlinDocumentQuery`1.<InitializeGraphTraversalAync>d__17.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Azure.Graphs.GremlinDocumentQuery`1.<ExecuteNextAsync>d__15`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Azure.Graphs.GremlinDocumentQuery`1.<ExecuteNextAsync>d__14.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at PlaygroundForms.Form1.<Query>d__10.MoveNext() in C:\\Users\\Benjamin\\source\\repos\\PlaygroundForms\\PlaygroundForms\\Form1.cs:line 157\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at PlaygroundForms.Form1.<btn_Query_Click>d__7.MoveNext() in C:\\Users\\Benjamin\\source\\repos\\PlaygroundForms\\PlaygroundForms\\Form1.cs:line 109",
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": "8\nCompileToFunction\nMicrosoft.Azure.Graphs, Version=0.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\nMicrosoft.Azure.Graphs.Runtime.WValueExpression\nMicrosoft.Azure.Graphs.Runtime.ScalarFunction CompileToFunction(Microsoft.Azure.Graphs.Runtime.QueryCompilationContext, Microsoft.Azure.Graphs.GraphCommand)",
"HResult": -2146233088,
"Source": "Microsoft.Azure.Graphs",
"WatsonBuckets": null
olivertowers commented 6 years ago

@BenjaBobs which client driver are you using to execute these queries?

BenjaBobs commented 6 years ago

I'm using Microsoft.Azure.Graphs and this is the case both for the emulator and CosmosDB in azure. Note that I haven't switched to the new Graph endpoint yet (don't know why I failed to mention this in the original post, as it seems relevant).

olivertowers commented 6 years ago

Microsoft.Azure.Graphs has been deprecated, so you should switch to connecting to CosmosDB Gremlin Server (see gremlin endpoint for your CosmosDB Account) using Tinkerpop Gremlin.NET client. A tutorial + sample is available here.

Regardless, I was able to repro the issue in both cases (query 2 produces a slightly different error message) and it looks like there is a bug related to unfold() + nested traversal on has() operator. Will look into this further and determine a suitable workaround.