Gremlin.net中P.Within方法数组转换异常问题求助
问题描述
我使用Gremlin.NET编写了如下代码:
var graphQuery = graph.V(source.ToString()); var graphOutCondition = __.OutE().HasLabel("Transport"); foreach (var filter in filters) { if (filter.Key.StartsWith("C")) { graphOutCondition = graphOutCondition.Has("C", P.Within(Clist)); } if (filter.Key.StartsWith("CT")) { graphOutCondition = graphOutCondition.Has(filter.Key,filter.Value); } if (filter.Key.StartsWith("TU")) { graphOutCondition = graphOutCondition.Where(__.Properties<string>().HasKey("EP_" + filter.Value.Clean())); } } graphQuery.Repeat(graphOutCondition.InV().SimplePath()) .Until(__.HasId(destination.ToString())); graphQuery.Path() .By(__.Id()).By(__.Id());
其中Clist是List<string>类型,包含多个值。运行代码时抛出异常:
Error: System.AggregateException: One or more errors occurred. (One or more errors occurred. (ScriptEvaluationError:
ActivityId : 29d7649d-0694-4089-9567-26506c67a010
ExceptionType : GraphSyntaxException
ExceptionMessage : Gremlin query syntax error: Unexpected token: '`'
发现数组被转换为System.Collections.Generic.List,尝试过直接传入列表、调用.ToArray()方法,结果均一致。使用的是Azure CosmosDB支持的Gremlin.NET 3.4.13版本,通过以下代码提交查询:
var result = gremlinClient.SubmitAsync<dynamic>(query.ToString()).Result
解决方案
问题根源在于调用query.ToString()将Gremlin查询转为字符串时,.NET集合类型无法被正确序列化为Gremlin可识别的数组语法,反而被转成了类似System.Collections.Generic.List的无效字符串,触发语法错误。
可以通过以下几种方式解决:
- 使用参数化查询:避免直接拼接字符串,改用Gremlin.NET的参数传递机制,将
Clist作为参数传入。这种方式不仅能解决语法问题,还能避免注入风险。示例代码:var parameters = new Dictionary<string, object> { { "clist", Clist } }; var graphQuery = graph.V(source.ToString()); var graphOutCondition = __.OutE().HasLabel("Transport"); foreach (var filter in filters) { if (filter.Key.StartsWith("C")) { // 使用参数引用替换直接传入集合 graphOutCondition = graphOutCondition.Has("C", P.Within(P.Of("clist"))); } // 其余过滤逻辑保持不变 if (filter.Key.StartsWith("CT")) { graphOutCondition = graphOutCondition.Has(filter.Key,filter.Value); } if (filter.Key.StartsWith("TU")) { graphOutCondition = graphOutCondition.Where(__.Properties<string>().HasKey("EP_" + filter.Value.Clean())); } } graphQuery.Repeat(graphOutCondition.InV().SimplePath()) .Until(__.HasId(destination.ToString())) .Path().By(__.Id()).By(__.Id()); // 传入参数提交查询 var result = gremlinClient.SubmitAsync<dynamic>(graphQuery, parameters).Result; - 手动序列化集合为Gremlin数组格式:如果必须使用
ToString()方式提交,可手动将Clist转换为Gremlin支持的数组字符串(如["val1","val2"]),替换查询中生成的无效集合表示。示例代码:// 手动构造Gremlin数组格式字符串,处理特殊字符避免语法错误 var clistGremlinStr = $"[{string.Join(",", Clist.Select(v => $"\"{v.Replace("\"", "\\\"")}\""))}]"; // 在过滤逻辑中使用构造好的字符串 if (filter.Key.StartsWith("C")) { graphOutCondition = graphOutCondition.Has("C", P.Within(clistGremlinStr)); } - 升级Gremlin.NET版本:后续版本可能修复了集合
ToString()序列化的问题,可尝试升级到兼容Azure CosmosDB的最新稳定版本。
内容的提问来源于stack exchange,提问作者arian shahesmaeili
相关产品推荐
相关产品推荐

