diff --git a/src/Gremlin.Net.CosmosDb/Serialization/GremlinQuerySerializer.cs b/src/Gremlin.Net.CosmosDb/Serialization/GremlinQuerySerializer.cs
index 61af028..7a8a441 100644
--- a/src/Gremlin.Net.CosmosDb/Serialization/GremlinQuerySerializer.cs
+++ b/src/Gremlin.Net.CosmosDb/Serialization/GremlinQuerySerializer.cs
@@ -30,6 +30,9 @@ internal sealed class GremlinQuerySerializer : IDisposable
DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
+ private static readonly string[] INSTRUCTIONS_REQUIRING_DOUBLE_UNDERSCORES_FOR_ANONYMOUS
+ = new[] { "in", "not", "V" };
+
private readonly JsonSerializerSettings _serializerSettings;
private readonly TextWriter _writer;
@@ -62,11 +65,22 @@ public GremlinQuerySerializer(TextWriter writer, JsonSerializerSettings serializ
/// The traversal.
/// traversal
public void Serialize(ITraversal traversal)
+ {
+ Serialize(traversal, startAnonTraversal: false);
+ }
+
+ ///
+ /// Serializes the specified traversal.
+ ///
+ /// The traversal.
+ /// true indicates that we're starting an anonymous traversal
+ /// traversal
+ private void Serialize(ITraversal traversal, bool startAnonTraversal)
{
if (traversal == null)
throw new ArgumentNullException(nameof(traversal));
- Serialize(traversal.Bytecode);
+ Serialize(traversal.Bytecode, startAnonTraversal);
}
///
@@ -74,6 +88,16 @@ public void Serialize(ITraversal traversal)
///
/// The bytecode.
private void Serialize(Bytecode bytecode)
+ {
+ Serialize(bytecode, startAnonTraversal: false);
+ }
+
+ ///
+ /// Serializes the specified bytecode.
+ ///
+ /// The bytecode.
+ /// true indicates that we're starting an anonymous traversal
+ private void Serialize(Bytecode bytecode, bool startAnonTraversal)
{
var first = true;
foreach (var instr in bytecode.SourceInstructions)
@@ -84,16 +108,25 @@ private void Serialize(Bytecode bytecode)
_writer.Write(instr.OperatorName);
first = false;
+ startAnonTraversal = false;
}
foreach (var instr in bytecode.StepInstructions)
{
if (!first)
+ {
_writer.Write('.');
+ }
+ else if (startAnonTraversal
+ && INSTRUCTIONS_REQUIRING_DOUBLE_UNDERSCORES_FOR_ANONYMOUS.Contains(instr.OperatorName))
+ {
+ _writer.Write("__.");
+ }
Serialize(instr);
first = false;
+ startAnonTraversal = false;
}
}
@@ -167,6 +200,8 @@ private void Serialize(P predicate)
var predicateValues = predicate.Value as IEnumerable;
if (predicateValues?.Any() ?? false)
SerializeListWithCommas(predicateValues);
+ else if (predicate.Value is ITraversal traversal)
+ Serialize(traversal, startAnonTraversal: true);
else
Serialize(predicate.Value);
}
@@ -223,7 +258,10 @@ private void SerializeListWithCommas(IEnumerable list)
if (addComma)
_writer.Write(',');
- Serialize(value);
+ if (value is ITraversal traversal)
+ Serialize(traversal, startAnonTraversal: true);
+ else
+ Serialize(value);
addComma = true;
}
diff --git a/test/Gremlin.Net.CosmosDb.Tests/TraversalSerialization/QuerySerializerTests.cs b/test/Gremlin.Net.CosmosDb.Tests/TraversalSerialization/QuerySerializerTests.cs
new file mode 100644
index 0000000..7c6f835
--- /dev/null
+++ b/test/Gremlin.Net.CosmosDb.Tests/TraversalSerialization/QuerySerializerTests.cs
@@ -0,0 +1,399 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Gremlin.Net.Process.Traversal;
+using Xunit;
+
+namespace Gremlin.Net.CosmosDb.Serialization
+{
+ public class QuerySerializerTests
+ {
+ private IGraphTraversalSource g = new GraphTraversalSource();
+
+ [Fact]
+ public void GetSingleVertex()
+ {
+ var id = Guid.NewGuid();
+ var traversal = g.V(id);
+ var actualGremlinQuery = traversal.ToGremlinQuery();
+ var expectedGremlinQuery = $@"g.V(""{id}"")";
+ Assert.Equal(expectedGremlinQuery, actualGremlinQuery);
+ }
+
+ #region HasId
+ [Fact(Skip = "Not supported")]
+ public void SerializeHasIdWithIEnumerableOfObjectsWithOneItem()
+ {
+ var list = new List