4
votes

So I am experimenting with CosmosDb and looking to use the Gremlin API for Vertex and Edge queries. I have a number of entities which will have multiple edge connections between such as "knows","trusts","likes" etc

I do however wish to have complex documents as vertices, so rather than use the gremlin syntax of text query with many properties (this seems very cumbersome) I have inserted documents using the documentDB API. Problem is once a document has been added (which comes back with query correctly and shows in the SQL query) I cannot then make any g.V() calls without getting a an error:

System.InvalidCastException: Invalid cast from 'System.String' to 'Newtonsoft.Json.Linq.JObject'.

I also can't add edges to these vertices.

So my question is, am I trying to do this the wrong way? Should my complex objects be held in a separate collection and then mirror their ids onto vertexes in a new collection?

Can you not use the Gremlin API and the Document API on the same collection?

Thanks for any advice.

Richard

Update for Oliver

This is the simple test document which creates fine using the documentdb library and is then shown when I perform an SQL Select * from c in the data explorer:

 {
        "id": "beea4756-2a25-4e2e-a7d9-457ad03dd56d",
        "title": "Test item",
        "description": "Test description",
        "purchaseUrl": "http://www.test.co.uk",
        "imageUrls": [
            "http://www.test.com",
            "http://www.test2.com"
        ],
        "label": "item",
        "created": "2017-10-09T12:41:49.0201322Z",
        "modified": "2017-10-09T12:41:49.0203021Z",
        "createdById": "TestUserId",
        "modifiedById": "TestUserId",
        "_rid": "jXNCAKbsIQABAAAAAAAAAA==",
        "_self": "dbs/jXNCAA==/colls/jXNCAKbsIQA=/docs/jXNCAKbsIQABAAAAAAAAAA==/",
        "_etag": "\"00000629-0000-0000-0000-59db6e8d0000\"",
        "_attachments": "attachments/",
        "_ts": 1507552909
    }

and this is the error I get when I use g.V() in the graph explorer in the Azure portal (or when I try any gremlin query or edge creation in my code):

    System.InvalidCastException: Invalid cast from 'System.String' to 'Newtonsoft.Json.Linq.JObject'.
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at Newtonsoft.Json.Linq.Extensions.Convert[T,U](T token)
   at Newtonsoft.Json.Linq.Extensions.<Convert>d__14`2.MoveNext()
   at Microsoft.Azure.Graphs.Runtime.VertexPropertyField.Replace(JProperty jproperty)
   at Microsoft.Azure.Graphs.Runtime.VertexField..ctor(GraphCommand graphCommand, JObject vertexObject)
   at Microsoft.Azure.Graphs.Common.VertexObjectCache.AddOrUpdateVertexField(VertexCompositeKey vertexKey, JObject vertexObject)
   at Microsoft.Azure.Graphs.Runtime.DocumentDBRuntime.<GetVertices>d__1.MoveNext()
   at Microsoft.Azure.Graphs.Runtime.Operators.FetchNodeOperator.<ComputeNextRecordAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.Runtime.Operators.GraphExecutionOperator.<NextAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.Runtime.Operators.ProjectOperator.<ComputeNextRecordAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.Runtime.Operators.GraphExecutionOperator.<NextAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.GraphTraversal.GraphTraversalIterator.<CurrentOperatorNextAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.GraphTraversal.GraphTraversalIterator.<MoveNextAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.GraphTraversal.<MoveNextAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.GremlinDocumentQuery`1.<ExecuteNextAsync>d__15`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Graphs.GremlinDocumentQuery`1.<ExecuteNextAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Portal.PlatformProxy.Graph.Controllers.GremlinQueriesController.<SubmitQueryAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Documents.Portal.PlatformProxy.Graph.Controllers.GremlinQueriesController.<Post>d__0.MoveNext()
1
I'm from Azure CosmosDB Graph team. We do support Gremlin API and Document API on the same collection, so this looks like a bug. Can you provide a sample document which repro's this issue in your question? Also are you using the latest Microsoft.Azure.Graphs package?Oliver Towers
Thanks for the update Oliver, I will put my code in a sample for you to test. I am using latest betas: "Microsoft.Azure.Graphs" Version="0.3.0-preview" and "Microsoft.Azure.DocumentDB.Core" Version="1.5.1" more soonRichard
Hi Richard, can you send out an email to [email protected] and include the link to this question. The team can work with you directly to try and get this unblocked.Oliver Towers
OK will do, thanks OliverRichard
@Richard - were you able to get this resolved? I'm getting the same exception when trying to do something similar.Kai G

1 Answers

4
votes

It is possible to mix and match the Graph and Document APIs in the same collection. However, it will only work if you insert the vertices and edges in the GraphSON format that is expected for graph documents. If you test running some gremlin inserts for both edges and vertices and then inspect the format of the documents in your collection by using the Document API you will see what the expected format looks like.

At my work we've built out a custom ORM that takes the C# POCOs representing our vertices and edges and builds up the appropriate structure using reflection before using the Document API to do the actual inserts. This way you get the best of both worlds.

The other option you've mentioned here of having one collection for representing pure relationship and another for storing the actual documents could also be a viable solution depending on the nature of the application you're building. There would definitely be a performance hit in the form of making extra network calls to fill in the actual documents as well as missing out on transactions in the form of SPROCs, etc.