Decide the intended attribute match semantics across Query Languages
- Dominant language
- TypeScript
- Stars
- 481
- Forks
- 108
- Avg merge
- 7d 16h
- Merged PRs (30d)
- 8
Description
## Goal
Neighbor expansion and Keyword Search both let a user type a value that an attribute must match, but the four code paths that implement the match disagree on what "match" means. Decide what the single intended semantic is, and how close each Query Language can get to it.
The divergences, as of `main`:
| | Gremlin | openCypher | SPARQL (query) | SPARQL (stored blank node, in memory) |
|---|---|---|---|---|
| Neighbor expansion | `containing(…)` — case-sensitive | `CONTAINS` — case-sensitive | `regex(str(?object), …, "i")` — case-insensitive | `RegExp(…, "gi")` — case-insensitive |
| Keyword Search, partial | `containing(…)` — case-sensitive | `CONTAINS` — case-sensitive | `regex(str(?value), …, "i")` — case-insensitive | n/a |
| Keyword Search, exact | `has(k, v)` | `= v` | `?value = v` — also full RDF term equality, so a language-tagged or typed literal will not match a plain one | n/a |
So the same typed value silently means different things depending on which database a user is connected to, and nothing records that as intentional.
Note the two SPARQL paths use regular-expression matching where the other languages use substring matching, so a value containing punctuation behaves differently there too.
The hard constraint that makes this a spike rather than a task: Graph Explorer's documented floor is TinkerPop 3.6.2 (Neptune 1.2.1.0), where the only substring predicate is `containing(…)`. `toLower()` arrives in 3.7.1, and Neptune forbids lambdas in every version — so a case-insensitive substring match is not straightforwardly reachable on the oldest supported Gremlin. Any convergence proposal has to say what happens there.
## Expected Outcome
- A decision on the intended match semantic for attribute filtering and Keyword Search partial match — case-sensitive or case-insensitive.
- A per-Query-Language conformance table showing what is achievable at each supported version floor, and what the fallback is where the intended semantic is unreachable.
- A recommendation on whether the remaining divergence should be declared and documented (e.g. an ADR plus a note in the contributor guide) or worked around.
- If a workaround is proposed for Gremlin at 3.6.2, an assessment of its query cost — index usage and whether it forces a scan.
- Whether SPARQL exact match should stay RDF term equality or compare on string value.
- A tasked-out follow-up, if the decision implies code changes.
## Related Issues
- Originated from #2031
- Related to #2020
> [!IMPORTANT]
> Internal only — this issue is maintained by the core team and is not accepting external contributions.
Contributor guide
Research direction
Start by comparing the four match paths identified in the issue: Gremlin, openCypher, SPARQL query, and in-memory SPARQL blank-node handling. Check the supported TinkerPop and Neptune version floors, then document the achievable semantics, fallback behavior, and query-cost implications. Done means a decided semantic, conformance table, divergence documentation recommendation, and any tasked follow-up.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- backend-api-design, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 15/100