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 <[email protected]>
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 <[email protected]>
> 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.
>>
>>
>>

Reply via email to