-
-
Notifications
You must be signed in to change notification settings - Fork 94
Description
Description
Bolt parameterized queries do not substitute $param values when used in MATCH node property maps ({id: $id}). The parameters are correctly received and work in other contexts — simple RETURN $x, WHERE clause comparisons, and arithmetic expressions all handle parameters correctly. Only the inline property map syntax fails to substitute.
Reproduction
Using the official Neo4j JavaScript driver v6.0.0 connecting to ArcadeDB 26.2.1 via Bolt.
Setup
# Start ArcadeDB with Bolt enabled
./bin/server.sh -Darcadedb.server.plugins="Bolt:com.arcadedb.bolt.BoltProtocolPlugin"Minimal test script (Node.js)
const neo4j = require('neo4j-driver'); // v6.0.0
const driver = neo4j.driver(
'bolt://127.0.0.1:7687',
neo4j.auth.basic('root', 'playwithdata'),
{ disableLosslessIntegers: true }
);
const session = driver.session({ database: 'mydb' });
// Step 1: Create a test vertex
await session.run("CREATE (t:TestNode {id: 'ABC123', name: 'test'}) RETURN t");
// Step 2: Simple parameter — WORKS ✅
const r1 = await session.run('RETURN $x AS val', { x: 'hello' });
console.log('RETURN $x:', r1.records[0].get('val')); // "hello"
// Step 3: MATCH with property map parameter — FAILS ❌
const r2 = await session.run(
'MATCH (t:TestNode {id: $id}) RETURN t.name AS name',
{ id: 'ABC123' }
);
console.log('MATCH {id: $id}:', r2.records.length, 'records'); // 0 records
// Step 4: WHERE clause parameter — WORKS ✅
const r3 = await session.run(
'MATCH (t:TestNode) WHERE t.id = $id RETURN t.name AS name',
{ id: 'ABC123' }
);
console.log('WHERE t.id = $id:', r3.records.length, 'records'); // 1 record
// Step 5: Literal in query — WORKS ✅
const r4 = await session.run(
"MATCH (t:TestNode {id: 'ABC123'}) RETURN t.name AS name"
);
console.log('Literal:', r4.records[0].get('name')); // "test"
// Step 6: Integer parameter — WORKS ✅
const r5 = await session.run('RETURN $n + 1 AS val', { n: neo4j.int(41) });
console.log('RETURN $n + 1:', r5.records[0].get('val')); // 42
await session.close();
await driver.close();Expected output
RETURN $x: hello
MATCH {id: $id}: 1 records
WHERE t.id = $id: 1 records
Literal: test
RETURN $n + 1: 42
Actual output
RETURN $x: hello
MATCH {id: $id}: 0 records ← BUG
WHERE t.id = $id: 1 records
Literal: test
RETURN $n + 1: 42
Analysis
- Parameter passing over Bolt works correctly —
RETURN $x,RETURN $n + 1, andWHERE t.id = $idall receive and use parameters properly - Only MATCH property map syntax fails —
MATCH (n {id: $id})does not substitute the parameter value, while the equivalentWHERE n.id = $idworks fine - The same queries work with literal values, confirming the data is correct and indexed
- Negotiated protocol: Bolt v4.4 (the driver offers v5.x, server negotiates down to 4.4)
Environment
- ArcadeDB: 26.2.1
- Neo4j JavaScript Driver: 6.0.0 (negotiates Bolt v4.4)
- OS: macOS (Apple Silicon)
- Java: openjdk version "25.0.2" 2026-01-20
Impact
This is a minor compatibility gap with Neo4j's Cypher dialect. In Neo4j, MATCH (n {id: $id}) and MATCH (n) WHERE n.id = $id are equivalent, and existing code or tutorials commonly use the property map form. Applications migrating from Neo4j may need to rewrite these patterns to use WHERE clauses instead, which is a straightforward change but easy to miss.
Workaround
Use explicit WHERE clauses instead of inline property maps:
-- Instead of this (broken):
MATCH (n:Label {id: $id}) RETURN n
-- Use this (works):
MATCH (n:Label) WHERE n.id = $id RETURN n