You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tinkerpop.apache.org by Stephen Mallette <sp...@gmail.com> on 2026/05/06 16:42:21 UTC

Re: Update on match

As I continue to tinker with match() I'm finding that in actual usage, I
want it to behave like the original match(). Basically, with the current
match() proposal we forced use of select() to follow match() as a standi-n
for RETURN (if i read the original posts right). If we don't have
match().select() then match() returns Optional.empty. I'm not sure that's
necessary and it actually creates a complication I'd called out with
serialization support for that and for language variants. This all seems
easily resolved by just making the new match work like the old one and have
it produce all the bindings as a Map if select() isn't present. So instead
of:

gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").limit(1)
==>Optional.empty
gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)")
match() cannot be a terminal step — use select() to access bound variables
Type ':help' or ':h' for help.
Display stack trace? [yN]n
gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").limit(10)
==>Optional.empty
==>Optional.empty

we'd instead get:

gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)")
==>[a:v[1],b:v[2]]
==>[a:v[1],b:v[4]]

which is essentially, all the bindings and equivalent to the old way:

gremlin> g.V().
......1>
match(__.as("a").hasLabel("person").out("knows").hasLabel("person").as("b"))
==>[a:v[1],b:v[2]]
==>[a:v[1],b:v[4]]

As when select() was forced, i don't think this precludes the use of
select() here. It in fact seems to fit quite well as it did before. I also
don't think it interferes with potential support of RETURN which would just
change which bindings are ultimately populated to the Map. We should also
get the original match().where() syntax immediately as a result of this
shift.


On Tue, Apr 14, 2026 at 7:45 AM Stephen Mallette <sp...@gmail.com>
wrote:

> Over the weekend, I experimented a bit with this proposal from Andrii,
> that was of positive discussion on this list a few months back, that helped
> bring some formality to the idea of making match() step take any
> declarative query language (like GQL) such that its results would be
> returned into a Gremlin traversal stream :
>
>
> https://github.com/apache/tinkerpop/blob/master/docs/src/dev/future/proposal-declarative-match-step-9.asciidoc
>
> I have the basics of it working:
>
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").select("a","b")
> ==>[a:v[1],b:v[2]]
> ==>[a:v[1],b:v[4]]
> gremlin> g.match("MATCH
> (a:person)-[:knows]->(b:person)").select("a","b").by('name')
> ==>[a:marko,b:vadas]
> ==>[a:marko,b:josh]
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person),
> (b)-[:created]->(s:software)").
> ......1>   select("a","b","s").by("name").by("name").by("name")
> ==>[a:marko,b:josh,s:lop]
> ==>[a:marko,b:josh,s:ripple]
>
> initially, I think this feature will come with the added restriction that
> match() is a provider implemented step for 4.0. In other words, there won't
> be generic support provided by the TinkerPop query processing engine. At
> least, that would not be the initial main goal. It could however be
> reserved for a future goal that arrives for 4.1 or some other later
> version. For 4.0, the focus would be a basic implementation for TinkerGraph
> only with a simple "TinkerGQL" grammar (i.e. a subset supported by
> TinkerGraph that focuses on pattern matching and basic filtering).
>
> I think that with these sorts of restrictions, this feature can
> comfortably land for 4.0 among the myriad of other things 4.0 will contain.
> It will allow both provider and user feedback on the feature in general and
> help set the stage for future work in this area. It will take a few days
> yet to get this to a PR stage - in the meantime please let me know if you
> have any thoughts on this.
>
>
>

Re: Update on match

Posted by Stephen Mallette <sp...@gmail.com>.
Here's another update on the latest with match() at this point. I've
expanded supported syntax a bit further to handle property filtering:

gremlin> g.match("MATCH (a:person)-[:created]->(s:software {name: 'lop'}),
(b:person)-[:created]->(s)").
......1>   where("a", neq("b")).
......2>   select("a", "b").by("name")
==>[a:marko,b:josh]
==>[a:marko,b:peter]
==>[a:josh,b:marko]
==>[a:josh,b:peter]
==>[a:peter,b:marko]
==>[a:peter,b:josh]
gremlin> g.match("MATCH (a:person)-[e:knows {weight: 1.0}]->(b:person)").
......1>   select("a", "e", "b").
......2>     by("name").by("weight").by("name")
==>[a:marko,e:1.0,b:josh]

I started this thread with the idea that this feature would only be
available to TinkerGraph, but as time has gone on, I sense that it's not a
huge step to abstract the implementation a bit to provide interfaces that
would allow this to work more generally for any graph that can provide some
basic graph statistics and other information to the GQL processing engine.
I think I will refactor a bit to offer a gql-gremlin package. In this way
the TinkerGQL syntax that we have, evolves in a more standard way rather
than something wholly specific to TinkerGraph and providers can decide if
they want to hook into it or not. I think at that point, this will be ready
for review.


On Wed, May 6, 2026 at 12:42 PM Stephen Mallette <sp...@gmail.com>
wrote:

> As I continue to tinker with match() I'm finding that in actual usage, I
> want it to behave like the original match(). Basically, with the current
> match() proposal we forced use of select() to follow match() as a standi-n
> for RETURN (if i read the original posts right). If we don't have
> match().select() then match() returns Optional.empty. I'm not sure that's
> necessary and it actually creates a complication I'd called out with
> serialization support for that and for language variants. This all seems
> easily resolved by just making the new match work like the old one and have
> it produce all the bindings as a Map if select() isn't present. So instead
> of:
>
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").limit(1)
> ==>Optional.empty
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)")
> match() cannot be a terminal step — use select() to access bound variables
> Type ':help' or ':h' for help.
> Display stack trace? [yN]n
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").limit(10)
> ==>Optional.empty
> ==>Optional.empty
>
> we'd instead get:
>
> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)")
> ==>[a:v[1],b:v[2]]
> ==>[a:v[1],b:v[4]]
>
> which is essentially, all the bindings and equivalent to the old way:
>
> gremlin> g.V().
> ......1>
> match(__.as("a").hasLabel("person").out("knows").hasLabel("person").as("b"))
> ==>[a:v[1],b:v[2]]
> ==>[a:v[1],b:v[4]]
>
> As when select() was forced, i don't think this precludes the use of
> select() here. It in fact seems to fit quite well as it did before. I also
> don't think it interferes with potential support of RETURN which would just
> change which bindings are ultimately populated to the Map. We should also
> get the original match().where() syntax immediately as a result of this
> shift.
>
>
> On Tue, Apr 14, 2026 at 7:45 AM Stephen Mallette <sp...@gmail.com>
> wrote:
>
>> Over the weekend, I experimented a bit with this proposal from Andrii,
>> that was of positive discussion on this list a few months back, that helped
>> bring some formality to the idea of making match() step take any
>> declarative query language (like GQL) such that its results would be
>> returned into a Gremlin traversal stream :
>>
>>
>> https://github.com/apache/tinkerpop/blob/master/docs/src/dev/future/proposal-declarative-match-step-9.asciidoc
>>
>> I have the basics of it working:
>>
>> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person)").select("a","b")
>> ==>[a:v[1],b:v[2]]
>> ==>[a:v[1],b:v[4]]
>> gremlin> g.match("MATCH
>> (a:person)-[:knows]->(b:person)").select("a","b").by('name')
>> ==>[a:marko,b:vadas]
>> ==>[a:marko,b:josh]
>> gremlin> g.match("MATCH (a:person)-[:knows]->(b:person),
>> (b)-[:created]->(s:software)").
>> ......1>   select("a","b","s").by("name").by("name").by("name")
>> ==>[a:marko,b:josh,s:lop]
>> ==>[a:marko,b:josh,s:ripple]
>>
>> initially, I think this feature will come with the added restriction that
>> match() is a provider implemented step for 4.0. In other words, there won't
>> be generic support provided by the TinkerPop query processing engine. At
>> least, that would not be the initial main goal. It could however be
>> reserved for a future goal that arrives for 4.1 or some other later
>> version. For 4.0, the focus would be a basic implementation for TinkerGraph
>> only with a simple "TinkerGQL" grammar (i.e. a subset supported by
>> TinkerGraph that focuses on pattern matching and basic filtering).
>>
>> I think that with these sorts of restrictions, this feature can
>> comfortably land for 4.0 among the myriad of other things 4.0 will contain.
>> It will allow both provider and user feedback on the feature in general and
>> help set the stage for future work in this area. It will take a few days
>> yet to get this to a PR stage - in the meantime please let me know if you
>> have any thoughts on this.
>>
>>
>>