Match 子句是无解的。行为不明确
Match clause is unsolvable. Behavior is not clear
我在运行时以编程方式编译查询,匹配子句是我能想到的执行此任务的更通用的方法。他们中的大多数 运行 都很好,但有些 return "Unsolvable pattern" 例外。
我已经检查过 here 是关于 SO 的唯一类似问题,但它没有回答或解释问题,至少对我来说是这样。
这是我失败的尝试。
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter2').out('hasTimeSeries').as('class')
)
与可怕的:
Exception in thread "main" java.lang.IllegalStateException: The provided match pattern is unsolvable: [[MatchStartStep(_m), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep], [MatchStartStep(_m2), VertexStep(OUT,[bar],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(_m1)], [MatchStartStep(_m1), VertexStep(OUT,[foo],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(_l)], [MatchStartStep(c), VertexStep(OUT,[is],vertex), HasStep([~label.eq(D)]), MatchEndStep], [MatchStartStep(_m1), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep], [MatchStartStep(_l), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep], [MatchStartStep(_m1), VertexStep(OUT,[beer],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(c)]]
现在这里有一个类似的可以代替:
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter1').out('hasTimeSeries').as('class')
)
我希望他们都return一个结果(尽管不同,因为它们是不同的模式)。
我想了解它失败的原因,并最终了解它是否是错误或我是否遗漏了什么。
编辑:
在玩具图(没有给出错误)和我的真实案例查询(我无法上传我的图示例)之间添加示例和平行关系
beer_graph=TinkerGraph.open()
g = beer_graph.traversal()
A = g.addV('A').next()
B = g.addV('B').next()
C = g.addV('C').next()
LOK = g.addV().next()
MOK1 = g.addV().next()
MOK2 = g.addV().next()
COK = g.addV().next()
g.V(LOK).addE('is').to(A)
g.V(MOK1).addE('is').to(B)
g.V(MOK2).addE('is').to(B)
g.V(COK).addE('is').to(C)
g.V(MOK1).addE('foo').to(LOK)
g.V(MOK2).addE('bar').to(MOK1)
g.V(MOK2).addE('beer').to(COK)
LKO = g.addV().property('guid', 'LKO').next()
MKO1 = g.addV().next()
MKO2 = g.addV().next()
CKO = g.addV().next()
g.V(LKO).addE('is').to(A)
g.V(MKO1).addE('is').to(B)
g.V(MKO2).addE('is').to(B)
g.V(CKO).addE('is').to(C)
g.V(MKO1).addE('foo').to(LKO)
g.V(MKO2).addE('bar').to(MKO1)
g.V(MKO1).addE('beer').to(CKO)
g.V().match(
__.as('_l').has('guid', 'LKO').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m1').outE('beer').inV().as('_c')
)
g.V().match(
__.as('_l').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m2').outE('beer').inV().as('_c')
)
两者都有效并且 return 正确地得到了结果。现在,远离玩具图,这些是我的项目在运行时构建的遍历:
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter2').out('hasTimeSeries').as('class')
)
[
[MatchStartStep(loc), HasStep([guid.eq(EGLD)]), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Main_Location)]), MatchEndStep],
[MatchStartStep(meter1), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Electricity_Meter)]), MatchEndStep],
[MatchStartStep(meter2), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Electricity_Meter)]), MatchEndStep],
[MatchStartStep(class), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Cleaned_Electricty_Meter)]), MatchEndStep],
[MatchStartStep(meter1), VertexStep(OUT,[hasLocation],vertex), MatchEndStep(loc)],
[MatchStartStep(meter2), VertexStep(OUT,[isPartOf],vertex), MatchEndStep(meter1)],
[MatchStartStep(meter2), VertexStep(OUT,[hasTimeSeries],vertex), MatchEndStep(class)]
]
与之前编译的相比
g.V().match(
__.as('_l').has('guid', 'LKO').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m1').outE('beer').inV().as('_c')
)
[
[MatchStartStep(_l), HasStep([guid.eq(LKO)]), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep],
[MatchStartStep(_m1), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep],
[MatchStartStep(_m2), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep],
[MatchStartStep(_c), VertexStep(OUT,[is],vertex), HasStep([~label.eq(C)]), MatchEndStep],
[MatchStartStep(_m1), VertexStep(OUT,[foo],vertex), MatchEndStep(_l)],
[MatchStartStep(_m2), VertexStep(OUT,[bar],vertex), MatchEndStep(_m1)],
[MatchStartStep(_m1), VertexStep(OUT,[beer],vertex), MatchEndStep(_c)]
]
为什么 "unsolvable pattern" 异常,为什么更改图表很重要?如果当前图形上的模式是 "unsolvable",我希望结果为空,而不是异常...
编辑 2:发现差异,不理解问题
我设法重建了 "incriminated" 脚本,这个不行...
g.V().match(
__.as("_loc").has("guid","EGLD").out("instanceOfSupClass").hasLabel("Main_Location"),
__.as("_meter1").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter1").outE("hasLocation").store("edges").inV().as("_loc"),
__.as("_meter1").outE("hasTimeSeries").store("edges").inV().as("class"),
__.as("_meter2").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter2").outE("isPartOf").store("edges").inV().as("_meter1"),
__.as("class").out("instanceOfSupClass").hasLabel("Virtual_Anomaly_Class_Time_Series")
)
这个有效...
g.V().match(
__.as("_meter2").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter2").outE("isPartOf").store("edges").inV().as("_meter1"),
__.as("_meter1").outE("hasLocation").store("edges").inV().as("_loc"),
__.as("_meter1").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("class").out("instanceOfSupClass").hasLabel("Virtual_Anomaly_Class_Time_Series"),
__.as("_loc").has("guid","EGLD").out("instanceOfSupClass").hasLabel("Main_Location"),
__.as("_meter1").outE("hasTimeSeries").store("edges").inV().as("class")
)
所以顺序很重要
我必须承认,我并不完全理解 MatchStep
代码。这里面有某种排序,但很明显,你不能依靠这种排序把你的模式变成可解的模式。
构建模式时,您应该确保第一个标签与传入元素匹配,并且所有其他 start-labels 都在 start-label 及其连接的 end-labels 之后.这有意义吗?以现代图表为例:
gremlin> g.V().match(
......1> __.as('a').out('knows').as('b'),
......2> __.as('b').out('created').as('c'))
==>[a:v[1],b:v[4],c:v[5]]
==>[a:v[1],b:v[4],c:v[3]]
gremlin> g.V().match(
......1> __.as('b').out('created').as('c'),
......2> __.as('a').out('knows').as('b'))
The provided match pattern is unsolvable: [[MatchStartStep(a), VertexStep(OUT,[knows],vertex), MatchEndStep(b)], [MatchStartStep(b), VertexStep(OUT,[created],vertex), MatchEndStep(c)]]
第一个模式很容易解决。从 a
可以转到 b
,一旦知道 b
是什么,就可以转到 c
。现在,第二次遍历只是交换了模式,但很容易看出为什么它无法解决;你从 b
开始,从那里你可以去 c
,但是不清楚 a
是从哪里来的。请注意,a.out.b
不能简单地转换为 b.in.a
,因为某些图形数据库具有单向边。但是,如果你知道边可以在两个方向上遍历,你手动把它转过来,那么遍历就可以了:
gremlin> g.V().match(
......1> __.as('b').out('created').as('c'),
......2> __.as('b').in('knows').as('a'))
==>[a:v[1],b:v[4],c:v[5]]
==>[a:v[1],b:v[4],c:v[3]]
在您的代码示例中,start-label 实际上应该是 _m2
以使所有其他标签都可解析。为什么它有效,即使您没有将其指定为第一个 start-label?我不知道,出于某种原因,内部排序算法给出了正确的模式顺序,但正如我最初提到的,这不应该是预期的。
我在运行时以编程方式编译查询,匹配子句是我能想到的执行此任务的更通用的方法。他们中的大多数 运行 都很好,但有些 return "Unsolvable pattern" 例外。
我已经检查过 here 是关于 SO 的唯一类似问题,但它没有回答或解释问题,至少对我来说是这样。
这是我失败的尝试。
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter2').out('hasTimeSeries').as('class')
)
与可怕的:
Exception in thread "main" java.lang.IllegalStateException: The provided match pattern is unsolvable: [[MatchStartStep(_m), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep], [MatchStartStep(_m2), VertexStep(OUT,[bar],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(_m1)], [MatchStartStep(_m1), VertexStep(OUT,[foo],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(_l)], [MatchStartStep(c), VertexStep(OUT,[is],vertex), HasStep([~label.eq(D)]), MatchEndStep], [MatchStartStep(_m1), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep], [MatchStartStep(_l), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep], [MatchStartStep(_m1), VertexStep(OUT,[beer],edge), StoreStep(edges), EdgeVertexStep(IN), MatchEndStep(c)]]
现在这里有一个类似的可以代替:
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter1').out('hasTimeSeries').as('class')
)
我希望他们都return一个结果(尽管不同,因为它们是不同的模式)。
我想了解它失败的原因,并最终了解它是否是错误或我是否遗漏了什么。
编辑: 在玩具图(没有给出错误)和我的真实案例查询(我无法上传我的图示例)之间添加示例和平行关系
beer_graph=TinkerGraph.open()
g = beer_graph.traversal()
A = g.addV('A').next()
B = g.addV('B').next()
C = g.addV('C').next()
LOK = g.addV().next()
MOK1 = g.addV().next()
MOK2 = g.addV().next()
COK = g.addV().next()
g.V(LOK).addE('is').to(A)
g.V(MOK1).addE('is').to(B)
g.V(MOK2).addE('is').to(B)
g.V(COK).addE('is').to(C)
g.V(MOK1).addE('foo').to(LOK)
g.V(MOK2).addE('bar').to(MOK1)
g.V(MOK2).addE('beer').to(COK)
LKO = g.addV().property('guid', 'LKO').next()
MKO1 = g.addV().next()
MKO2 = g.addV().next()
CKO = g.addV().next()
g.V(LKO).addE('is').to(A)
g.V(MKO1).addE('is').to(B)
g.V(MKO2).addE('is').to(B)
g.V(CKO).addE('is').to(C)
g.V(MKO1).addE('foo').to(LKO)
g.V(MKO2).addE('bar').to(MKO1)
g.V(MKO1).addE('beer').to(CKO)
g.V().match(
__.as('_l').has('guid', 'LKO').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m1').outE('beer').inV().as('_c')
)
g.V().match(
__.as('_l').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m2').outE('beer').inV().as('_c')
)
两者都有效并且 return 正确地得到了结果。现在,远离玩具图,这些是我的项目在运行时构建的遍历:
g.V().match(
__.as('loc').has('guid','EGLD').out('instanceOfSupClass').hasLabel('Main_Location'),
__.as('meter1').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('meter2').out('instanceOfSupClass').hasLabel('Electricity_Meter'),
__.as('class').out('instanceOfSupClass').hasLabel('Cleaned_Electricty_Meter'),
__.as('meter1').out('hasLocation').as('loc'),
__.as('meter2').out('isPartOf').as('meter1'),
__.as('meter2').out('hasTimeSeries').as('class')
)
[
[MatchStartStep(loc), HasStep([guid.eq(EGLD)]), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Main_Location)]), MatchEndStep],
[MatchStartStep(meter1), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Electricity_Meter)]), MatchEndStep],
[MatchStartStep(meter2), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Electricity_Meter)]), MatchEndStep],
[MatchStartStep(class), VertexStep(OUT,[instanceOfSupClass],vertex), HasStep([~label.eq(Cleaned_Electricty_Meter)]), MatchEndStep],
[MatchStartStep(meter1), VertexStep(OUT,[hasLocation],vertex), MatchEndStep(loc)],
[MatchStartStep(meter2), VertexStep(OUT,[isPartOf],vertex), MatchEndStep(meter1)],
[MatchStartStep(meter2), VertexStep(OUT,[hasTimeSeries],vertex), MatchEndStep(class)]
]
与之前编译的相比
g.V().match(
__.as('_l').has('guid', 'LKO').outE('is').inV().hasLabel('A'),
__.as('_m1').outE('is').inV().hasLabel('B'),
__.as('_m2').outE('is').inV().hasLabel('B'),
__.as('_c').outE('is').inV().hasLabel('C'),
__.as('_m1').outE('foo').inV().as('_l'),
__.as('_m2').outE('bar').inV().as('_m1'),
__.as('_m1').outE('beer').inV().as('_c')
)
[
[MatchStartStep(_l), HasStep([guid.eq(LKO)]), VertexStep(OUT,[is],vertex), HasStep([~label.eq(A)]), MatchEndStep],
[MatchStartStep(_m1), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep],
[MatchStartStep(_m2), VertexStep(OUT,[is],vertex), HasStep([~label.eq(B)]), MatchEndStep],
[MatchStartStep(_c), VertexStep(OUT,[is],vertex), HasStep([~label.eq(C)]), MatchEndStep],
[MatchStartStep(_m1), VertexStep(OUT,[foo],vertex), MatchEndStep(_l)],
[MatchStartStep(_m2), VertexStep(OUT,[bar],vertex), MatchEndStep(_m1)],
[MatchStartStep(_m1), VertexStep(OUT,[beer],vertex), MatchEndStep(_c)]
]
为什么 "unsolvable pattern" 异常,为什么更改图表很重要?如果当前图形上的模式是 "unsolvable",我希望结果为空,而不是异常...
编辑 2:发现差异,不理解问题
我设法重建了 "incriminated" 脚本,这个不行...
g.V().match(
__.as("_loc").has("guid","EGLD").out("instanceOfSupClass").hasLabel("Main_Location"),
__.as("_meter1").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter1").outE("hasLocation").store("edges").inV().as("_loc"),
__.as("_meter1").outE("hasTimeSeries").store("edges").inV().as("class"),
__.as("_meter2").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter2").outE("isPartOf").store("edges").inV().as("_meter1"),
__.as("class").out("instanceOfSupClass").hasLabel("Virtual_Anomaly_Class_Time_Series")
)
这个有效...
g.V().match(
__.as("_meter2").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("_meter2").outE("isPartOf").store("edges").inV().as("_meter1"),
__.as("_meter1").outE("hasLocation").store("edges").inV().as("_loc"),
__.as("_meter1").out("instanceOfSupClass").hasLabel("Electricity_Meter"),
__.as("class").out("instanceOfSupClass").hasLabel("Virtual_Anomaly_Class_Time_Series"),
__.as("_loc").has("guid","EGLD").out("instanceOfSupClass").hasLabel("Main_Location"),
__.as("_meter1").outE("hasTimeSeries").store("edges").inV().as("class")
)
所以顺序很重要
我必须承认,我并不完全理解 MatchStep
代码。这里面有某种排序,但很明显,你不能依靠这种排序把你的模式变成可解的模式。
构建模式时,您应该确保第一个标签与传入元素匹配,并且所有其他 start-labels 都在 start-label 及其连接的 end-labels 之后.这有意义吗?以现代图表为例:
gremlin> g.V().match(
......1> __.as('a').out('knows').as('b'),
......2> __.as('b').out('created').as('c'))
==>[a:v[1],b:v[4],c:v[5]]
==>[a:v[1],b:v[4],c:v[3]]
gremlin> g.V().match(
......1> __.as('b').out('created').as('c'),
......2> __.as('a').out('knows').as('b'))
The provided match pattern is unsolvable: [[MatchStartStep(a), VertexStep(OUT,[knows],vertex), MatchEndStep(b)], [MatchStartStep(b), VertexStep(OUT,[created],vertex), MatchEndStep(c)]]
第一个模式很容易解决。从 a
可以转到 b
,一旦知道 b
是什么,就可以转到 c
。现在,第二次遍历只是交换了模式,但很容易看出为什么它无法解决;你从 b
开始,从那里你可以去 c
,但是不清楚 a
是从哪里来的。请注意,a.out.b
不能简单地转换为 b.in.a
,因为某些图形数据库具有单向边。但是,如果你知道边可以在两个方向上遍历,你手动把它转过来,那么遍历就可以了:
gremlin> g.V().match(
......1> __.as('b').out('created').as('c'),
......2> __.as('b').in('knows').as('a'))
==>[a:v[1],b:v[4],c:v[5]]
==>[a:v[1],b:v[4],c:v[3]]
在您的代码示例中,start-label 实际上应该是 _m2
以使所有其他标签都可解析。为什么它有效,即使您没有将其指定为第一个 start-label?我不知道,出于某种原因,内部排序算法给出了正确的模式顺序,但正如我最初提到的,这不应该是预期的。