grafeo-ogm 2.3.5 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.4.0 (2026-10-18) — `@cypher` fields keep every node exactly once
4
+
5
+ > **Minor release with a behavior change.** Reads that select, filter or sort a `@cypher` field can return a **different number of rows** than in 2.3.x. Nodes that were silently dropped now appear, with `null` for the field, and duplicated nodes now appear once. See *Behavior changes*.
6
+
7
+ ### 🐛 A `@cypher` statement with zero or several rows dropped or duplicated the node ([#9](https://github.com/neomodular/grafeo-ogm/issues/9))
8
+
9
+ A top-level `@cypher` field was computed with a plain `CALL { <statement> }`, and a CALL that yields zero rows removes the outer row, while one that yields several multiplies it. The same prelude backs the select, `where` and `options.sort` scopes, so with a statement like `MATCH (this)-[:HAS_STATUS]->(s) RETURN s.name AS status`:
10
+
11
+ | Operation | 2.3.x | 2.4.0 |
12
+ |---|---|---|
13
+ | `find`, selecting `status` | node without a status **dropped**; node with 2 statuses **returned twice** | each node once: `null` / first status |
14
+ | `where: { status: null }` | **never matched** | matches nodes without a status |
15
+ | `where: { status_NOT: x }` | duplicates | each node once |
16
+ | `options.sort: [{ status }]` | nodes without a status **missing**, others duplicated | every node once; `null` sorts per Neo4j (last on `ASC`) |
17
+ | `count({ where })` on `status` | undercounted / overcounted | agrees with `find` |
18
+ | `create` / `update` / `upsert` selecting `status` | **`[]` (or `null`) even though the write committed** | the written node |
19
+
20
+ Each prelude now runs the statement in an inner `CALL` and reduces its `columnName` column with `head(collect(…))`. A grouping-free aggregation always yields exactly one row, so every node is kept once. That matches how nested selections already projected `@cypher` fields (`head(COLLECT { … })`). The shape works on every Neo4j 5.x, unlike `OPTIONAL CALL` (5.24+), and statements may still return extra columns.
21
+
22
+ ### Behavior changes
23
+
24
+ - **Row counts can change** for any read that selects, filters or sorts a top-level `@cypher` field. Code that relied on such nodes being absent, for example as an implicit "has a status" filter, should filter explicitly: `where: { status_NOT: null }`.
25
+ - **With several statement rows, the first one wins.** Add an `ORDER BY` to the `@cypher` statement if it matters which value is picked.
26
+ - **Generated Cypher changes** for queries that use `@cypher` fields. If you pin compiled Cypher in tests, expect the new prelude shape. Queries without `@cypher` fields are byte-identical.
27
+
28
+ A new opt-in live suite, `tests/integration/cypher-field-row-semantics.spec.ts`, pins each row above as a database outcome. Against Neo4j 5.26.32, all 7 cases fail on 2.3.6.
29
+
30
+ ## 2.3.6 (2026-10-18) — `searchByPhrase` works
31
+
32
+ ### 🐛 `searchByPhrase` called a function as a procedure ([#13](https://github.com/neomodular/grafeo-ogm/issues/13))
33
+
34
+ `searchByPhrase` emitted `CALL genai.vector.encode(…) YIELD vector`. In the GenAI plugin, `genai.vector.encode` is a **function**: the plugin's procedures are only `genai.vector.encodeBatch` and `genai.vector.listEncodingProviders`. So every call failed with `There is no procedure with the name 'genai.vector.encode' registered`. The embedding is now computed in a `WITH genai.vector.encode(…) AS __v_encoded_N` ahead of the `db.index.vector.queryNodes` call. `searchByVector` is unchanged.
35
+
36
+ A new opt-in live suite, `tests/integration/vector-phrase.spec.ts`, runs when `NEO4J_GENAI_URI` points at a server with the GenAI plugin, for example `neo4j:5.26` with `NEO4J_PLUGINS=["genai"]`. It never contacts an embedding provider: an empty provider config makes the plugin fail locally, and the test asserts that this config error is what comes back, not the missing-procedure error.
37
+
3
38
  ## 2.3.5 (2026-10-18) — `create` with several inputs returns every node
4
39
 
5
40
  ### 🐛 Only the first created node was returned ([#12](https://github.com/neomodular/grafeo-ogm/issues/12))
package/README.md CHANGED
@@ -1100,6 +1100,13 @@ type Book @node {
1100
1100
 
1101
1101
  `statement` is the Cypher body — `this` is bound to the matched node. `columnName` is the alias the OGM reads from the `RETURN` clause; if omitted it defaults to the field name.
1102
1102
 
1103
+ **Row semantics (v2.4.0+).** A `@cypher` field always resolves to **one value per node**, in every scope (select, where, sort, nested selections):
1104
+
1105
+ - If the statement returns **no rows**, the field is `null` and the node is still returned. A filter like `where: { status: null }` matches it, and it sorts as `null`.
1106
+ - If the statement returns **several rows**, the field takes the **first** row's `columnName` value, and the node is returned once. Add an `ORDER BY` to the statement when it matters which row is first.
1107
+
1108
+ Before v2.4.0, top-level fields dropped nodes whose statement returned no rows and duplicated nodes whose statement returned several. See the [2.4.0 changelog](CHANGELOG.md).
1109
+
1103
1110
  > **⚠️ Security — `@cypher` SDL is trusted code, not data.** The `statement` argument is interpolated **verbatim** into the compiled Cypher (no parameterisation, no escaping). Treat `@cypher` directives the same way you treat `eval()` in your application code: the string MUST be a constant authored at development time, never built from runtime input. If your `typeDefs` are ever assembled from user input, environment variables, database records, or remote configuration, you have a Cypher-injection vector equivalent to RCE on the database (`MATCH (n) DETACH DELETE n RETURN '' AS x` in a `statement` will wipe the graph). The grafeo-ogm runtime cannot distinguish between developer-authored and user-derived SDL — that boundary is the application's responsibility.
1104
1111
 
1105
1112
  #### Using @cypher in SELECT
@@ -1 +1 @@
1
- {"version":3,"file":"vector.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAe,MAAM,iBAAiB,CAAC;AAM9D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;;IAOzB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,CAAC,EAAE,MAAM,CAAC;QACV,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAwBhB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,CAAC,EAAE,MAAM,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAyChB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAgB1B"}
1
+ {"version":3,"file":"vector.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAe,MAAM,iBAAiB,CAAC;AAM9D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;;IAOzB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,CAAC,EAAE,MAAM,CAAC;QACV,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAwBhB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,CAAC,EAAE,MAAM,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IA2ChB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAgB1B"}
@@ -64,8 +64,10 @@ class VectorCompiler {
64
64
  const providerParam = `v_provider_${suffix}`;
65
65
  const providerCfgParam = `v_providerConfig_${suffix}`;
66
66
  const encodedVar = `__v_encoded_${suffix}`;
67
+ // `genai.vector.encode` is a FUNCTION (only `encodeBatch` is a
68
+ // procedure), so it is evaluated in a WITH, not CALLed.
67
69
  const cypher = [
68
- `CALL genai.vector.encode($${phraseParam}, $${providerParam}, $${providerCfgParam}) YIELD vector AS ${encodedVar}`,
70
+ `WITH genai.vector.encode($${phraseParam}, $${providerParam}, $${providerCfgParam}) AS ${encodedVar}`,
69
71
  `CALL db.index.vector.queryNodes($${nameParam}, $${kParam}, ${encodedVar}) YIELD node AS n, score`,
70
72
  ].join('\n');
71
73
  const params = {
@@ -1 +1 @@
1
- {"version":3,"file":"vector.compiler.js","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vector.compiler.js","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,20 @@
1
1
  import type { PropertyDefinition } from '../schema/types';
2
2
  /**
3
- * Builds the `CALL { ... }` subquery that projects a `@cypher` field. Same
4
- * shape as the v1.5.0 sort prelude — `this` is rebound from the outer node
5
- * variable inside the subquery, no text substitution.
3
+ * Builds the `CALL { ... }` subquery that projects a `@cypher` field (used
4
+ * by the SELECT, WHERE and sort preludes). `this` is rebound from the
5
+ * outer node variable inside the subquery, no text substitution.
6
+ *
7
+ * Row-preserving: the user's statement runs in an inner CALL and its
8
+ * `columnName` column is reduced with `head(collect(...))`. A grouping-
9
+ * free aggregation always yields exactly ONE row, so the outer row is
10
+ * kept with `null` when the statement returns no rows, and kept once
11
+ * (first value) when it returns several — matching the nested
12
+ * `head(COLLECT { ... })` projection. Pre-2.4.0 the statement was CALLed
13
+ * directly, which dropped the node on zero rows and duplicated it on many.
14
+ * Works on every Neo4j 5.x (unlike `OPTIONAL CALL`, 5.24+) and still lets
15
+ * the statement return extra columns (unlike `COLLECT { }`).
6
16
  */
7
- export declare function buildCypherFieldCall(statement: string, nodeVar: string): string;
17
+ export declare function buildCypherFieldCall(statement: string, nodeVar: string, columnName: string): string;
8
18
  /**
9
19
  * Builds an inline `head(COLLECT { ... })` subquery expression for a
10
20
  * `@cypher` scalar field. Used inside contexts where a CALL prelude cannot
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-field-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAQR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAWzB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAfjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;;IAG7C,sEAAsE;IACrD,OAAO,EAAE,MAAM;IAChC,2DAA2D;IAC1C,YAAY,GAAE,aAAa,CAAC,MAAM,CAAM;IACzD,4DAA4D;IAC3C,cAAc,GAAE,MAAe;IAKlD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM;IAiChE,+CAA+C;IAC/C,MAAM,IAAI,OAAO;IAIjB,sEAAsE;IACtE,IAAI,IAAI,MAAM,EAAE;IAIhB,wDAAwD;IACxD,OAAO,IAAI,MAAM,EAAE;IAInB,0CAA0C;IAC1C,UAAU,IAAI,MAAM;CAGrB"}
1
+ {"version":3,"file":"cypher-field-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAaR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAWzB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAfjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;;IAG7C,sEAAsE;IACrD,OAAO,EAAE,MAAM;IAChC,2DAA2D;IAC1C,YAAY,GAAE,aAAa,CAAC,MAAM,CAAM;IACzD,4DAA4D;IAC3C,cAAc,GAAE,MAAe;IAKlD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM;IAiChE,+CAA+C;IAC/C,MAAM,IAAI,OAAO;IAIjB,sEAAsE;IACtE,IAAI,IAAI,MAAM,EAAE;IAIhB,wDAAwD;IACxD,OAAO,IAAI,MAAM,EAAE;IAInB,0CAA0C;IAC1C,UAAU,IAAI,MAAM;CAGrB"}
@@ -5,16 +5,31 @@ exports.buildCypherFieldCall = buildCypherFieldCall;
5
5
  exports.buildInlineCypherFieldExpr = buildInlineCypherFieldExpr;
6
6
  const validation_1 = require("./validation");
7
7
  /**
8
- * Builds the `CALL { ... }` subquery that projects a `@cypher` field. Same
9
- * shape as the v1.5.0 sort prelude — `this` is rebound from the outer node
10
- * variable inside the subquery, no text substitution.
8
+ * Builds the `CALL { ... }` subquery that projects a `@cypher` field (used
9
+ * by the SELECT, WHERE and sort preludes). `this` is rebound from the
10
+ * outer node variable inside the subquery, no text substitution.
11
+ *
12
+ * Row-preserving: the user's statement runs in an inner CALL and its
13
+ * `columnName` column is reduced with `head(collect(...))`. A grouping-
14
+ * free aggregation always yields exactly ONE row, so the outer row is
15
+ * kept with `null` when the statement returns no rows, and kept once
16
+ * (first value) when it returns several — matching the nested
17
+ * `head(COLLECT { ... })` projection. Pre-2.4.0 the statement was CALLed
18
+ * directly, which dropped the node on zero rows and duplicated it on many.
19
+ * Works on every Neo4j 5.x (unlike `OPTIONAL CALL`, 5.24+) and still lets
20
+ * the statement return extra columns (unlike `COLLECT { }`).
11
21
  */
12
- function buildCypherFieldCall(statement, nodeVar) {
22
+ function buildCypherFieldCall(statement, nodeVar, columnName) {
23
+ const col = (0, validation_1.escapeIdentifier)(columnName);
13
24
  return [
14
25
  `CALL {`,
15
26
  ` WITH ${nodeVar}`,
16
- ` WITH ${nodeVar} AS this`,
17
- ` ${statement}`,
27
+ ` CALL {`,
28
+ ` WITH ${nodeVar}`,
29
+ ` WITH ${nodeVar} AS this`,
30
+ ` ${statement}`,
31
+ ` }`,
32
+ ` RETURN head(collect(${col})) AS ${col}`,
18
33
  `}`,
19
34
  ].join('\n');
20
35
  }
@@ -94,7 +109,7 @@ class CypherFieldScope {
94
109
  (0, validation_1.assertSafeIdentifier)(alias, '@cypher alias');
95
110
  const carry = [...this.preserveVars, ...this.carriedAliases];
96
111
  const carryStr = carry.length ? `, ${carry.join(', ')}` : '';
97
- this.callLines.push(buildCypherFieldCall(propDef.cypherStatement, this.nodeVar));
112
+ this.callLines.push(buildCypherFieldCall(propDef.cypherStatement, this.nodeVar, columnName));
98
113
  this.callLines.push(`WITH ${this.nodeVar}${carryStr}, ${(0, validation_1.escapeIdentifier)(columnName)} AS ${alias}`);
99
114
  this.carriedAliases.push(alias);
100
115
  this.aliases.set(fieldName, alias);
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-field-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cypher-field-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":";;;AAkBA,oDAiBC;AAiBD,gEAKC;AAxDD,6CAAsE;AAEtE;;;;;;;;;;;;;;GAcG;AACH,SAAgB,oBAAoB,CAClC,SAAiB,EACjB,OAAe,EACf,UAAkB;IAElB,MAAM,GAAG,GAAG,IAAA,6BAAgB,EAAC,UAAU,CAAC,CAAC;IACzC,OAAO;QACL,QAAQ;QACR,UAAU,OAAO,EAAE;QACnB,UAAU;QACV,YAAY,OAAO,EAAE;QACrB,YAAY,OAAO,UAAU;QAC7B,OAAO,SAAS,EAAE;QAClB,KAAK;QACL,yBAAyB,GAAG,SAAS,GAAG,EAAE;QAC1C,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,0BAA0B,CACxC,SAAiB,EACjB,OAAe;IAEf,OAAO,uBAAuB,OAAO,eAAe,SAAS,MAAM,CAAC;AACtE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,gBAAgB;IAU3B;IACE,sEAAsE;IACrD,OAAe;IAChC,2DAA2D;IAC1C,eAAsC,EAAE;IACzD,4DAA4D;IAC3C,iBAAyB,MAAM;QAJ/B,YAAO,GAAP,OAAO,CAAQ;QAEf,iBAAY,GAAZ,YAAY,CAA4B;QAExC,mBAAc,GAAd,cAAc,CAAiB;QAflD;;;;WAIG;QACc,YAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QACpC,cAAS,GAAa,EAAE,CAAC;QACzB,mBAAc,GAAa,EAAE,CAAC;QAU7C,IAAA,iCAAoB,EAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,SAAiB,EAAE,OAA2B;QACrD,IAAA,iCAAoB,EAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,IAAI,CAAC,OAAO,CAAC,eAAe;YAC1B,MAAM,IAAI,KAAK,CACb,oCAAoC,SAAS,4BAA4B,CAC1E,CAAC;QAEJ,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,IAAI,SAAS,CAAC;QACzD,IAAA,iCAAoB,EAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC;QACpE,IAAA,iCAAoB,EAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAE7C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAE7D,IAAI,CAAC,SAAS,CAAC,IAAI,CACjB,oBAAoB,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CACxE,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,CACjB,QAAQ,IAAI,CAAC,OAAO,GAAG,QAAQ,KAAK,IAAA,6BAAgB,EAAC,UAAU,CAAC,OAAO,KAAK,EAAE,CAC/E,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAEnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,+CAA+C;IAC/C,MAAM;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,sEAAsE;IACtE,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED,wDAAwD;IACxD,OAAO;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,0CAA0C;IAC1C,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAhFD,4CAgFC"}
@@ -1,23 +1,16 @@
1
1
  import type { PropertyDefinition } from '../schema/types';
2
2
  /**
3
3
  * Builds the `CALL { ... }` subquery used to project an `@cypher` field
4
- * for `ORDER BY`. The user's statement is embedded verbatim with `this`
5
- * rebound from the outer node variable — no text substitution.
4
+ * for `ORDER BY` — the same row-preserving shape as the SELECT / WHERE
5
+ * preludes (see `buildCypherFieldCall`): a node whose statement returns
6
+ * no rows sorts with `null` instead of vanishing, and one returning
7
+ * several rows sorts once.
6
8
  *
7
9
  * The caller is expected to follow this CALL with its own `WITH` clause
8
10
  * to rename the projected column (`<columnName>`) to a unique alias
9
11
  * (e.g. `__sort_<fieldName>`) and carry forward any prior sort aliases.
10
- *
11
- * Example output:
12
- * ```cypher
13
- * CALL {
14
- * WITH n
15
- * WITH n AS this
16
- * MATCH (this)-[:HAS_STATUS]->(s) RETURN s.name AS statusName
17
- * }
18
- * ```
19
12
  */
20
- export declare function buildCypherSortProjection(statement: string, nodeVar: string): string;
13
+ export declare function buildCypherSortProjection(statement: string, nodeVar: string, columnName: string): string;
21
14
  /**
22
15
  * Compiles a `sort` array (mixed stored-field + `@cypher`-field entries)
23
16
  * into the Cypher fragments needed before and after the `RETURN` clause.
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-sort-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAS1D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAQR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAClE,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDnC"}
1
+ {"version":3,"file":"cypher-sort-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAU1D;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAClE,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDnC"}
@@ -2,33 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildCypherSortProjection = buildCypherSortProjection;
4
4
  exports.compileSortClause = compileSortClause;
5
+ const cypher_field_projection_1 = require("./cypher-field-projection");
5
6
  const validation_1 = require("./validation");
6
7
  /**
7
8
  * Builds the `CALL { ... }` subquery used to project an `@cypher` field
8
- * for `ORDER BY`. The user's statement is embedded verbatim with `this`
9
- * rebound from the outer node variable — no text substitution.
9
+ * for `ORDER BY` — the same row-preserving shape as the SELECT / WHERE
10
+ * preludes (see `buildCypherFieldCall`): a node whose statement returns
11
+ * no rows sorts with `null` instead of vanishing, and one returning
12
+ * several rows sorts once.
10
13
  *
11
14
  * The caller is expected to follow this CALL with its own `WITH` clause
12
15
  * to rename the projected column (`<columnName>`) to a unique alias
13
16
  * (e.g. `__sort_<fieldName>`) and carry forward any prior sort aliases.
14
- *
15
- * Example output:
16
- * ```cypher
17
- * CALL {
18
- * WITH n
19
- * WITH n AS this
20
- * MATCH (this)-[:HAS_STATUS]->(s) RETURN s.name AS statusName
21
- * }
22
- * ```
23
17
  */
24
- function buildCypherSortProjection(statement, nodeVar) {
25
- return [
26
- `CALL {`,
27
- ` WITH ${nodeVar}`,
28
- ` WITH ${nodeVar} AS this`,
29
- ` ${statement}`,
30
- `}`,
31
- ].join('\n');
18
+ function buildCypherSortProjection(statement, nodeVar, columnName) {
19
+ return (0, cypher_field_projection_1.buildCypherFieldCall)(statement, nodeVar, columnName);
32
20
  }
33
21
  /**
34
22
  * Compiles a `sort` array (mixed stored-field + `@cypher`-field entries)
@@ -73,7 +61,7 @@ function compileSortClause(args) {
73
61
  const alias = `__sort_${field}`;
74
62
  const columnName = propDef.cypherColumnName ?? field;
75
63
  (0, validation_1.assertSafeIdentifier)(columnName, '@cypher columnName');
76
- preLines.push(buildCypherSortProjection(propDef.cypherStatement, nodeVar));
64
+ preLines.push(buildCypherSortProjection(propDef.cypherStatement, nodeVar, columnName));
77
65
  const carry = [...preserveVars, ...carriedAliases];
78
66
  const carryStr = carry.length ? `, ${carry.join(', ')}` : '';
79
67
  preLines.push(`WITH ${nodeVar}${carryStr}, ${(0, validation_1.escapeIdentifier)(columnName)} AS ${alias}`);
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-sort-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":";;AA2BA,8DAWC;AAmBD,8CAqDC;AA7GD,6CAMsB;AAEtB;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,yBAAyB,CACvC,SAAiB,EACjB,OAAe;IAEf,OAAO;QACL,QAAQ;QACR,UAAU,OAAO,EAAE;QACnB,UAAU,OAAO,UAAU;QAC3B,KAAK,SAAS,EAAE;QAChB,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,iBAAiB,CAAC,IAKjC;IACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAClE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,uEAAuE;QACvE,kEAAkE;QAClE,IAAA,8BAAiB,EAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAiC,CAAC,CAAC;QAClE,yEAAyE;QACzE,iEAAiE;QACjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,2EAA2E;QAC3E,qEAAqE;QACrE,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO;YAAE,IAAA,iCAAoB,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACrE,IAAA,gCAAmB,EAAC,OAAO,CAAC,CAAC;QAE7B,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,IAAA,gCAAmB,EAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,UAAU,KAAK,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC;YACrD,IAAA,iCAAoB,EAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;YAEvD,QAAQ,CAAC,IAAI,CACX,yBAAyB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,CAC5D,CAAC;YAEF,MAAM,KAAK,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,cAAc,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,QAAQ,CAAC,IAAI,CACX,QAAQ,OAAO,GAAG,QAAQ,KAAK,IAAA,6BAAgB,EAAC,UAAU,CAAC,OAAO,KAAK,EAAE,CAC1E,CAAC;YACF,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,cAAc,EAAE,CAAC,CAAC;QAC/C,CAAC;;YACC,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,IAAA,6BAAgB,EAAC,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;KACpE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cypher-sort-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":";;AAqBA,8DAMC;AAmBD,8CAqDC;AAlGD,uEAAiE;AACjE,6CAMsB;AAEtB;;;;;;;;;;GAUG;AACH,SAAgB,yBAAyB,CACvC,SAAiB,EACjB,OAAe,EACf,UAAkB;IAElB,OAAO,IAAA,8CAAoB,EAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,iBAAiB,CAAC,IAKjC;IACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAClE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,uEAAuE;QACvE,kEAAkE;QAClE,IAAA,8BAAiB,EAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAiC,CAAC,CAAC;QAClE,yEAAyE;QACzE,iEAAiE;QACjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,2EAA2E;QAC3E,qEAAqE;QACrE,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO;YAAE,IAAA,iCAAoB,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACrE,IAAA,gCAAmB,EAAC,OAAO,CAAC,CAAC;QAE7B,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,IAAA,gCAAmB,EAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,UAAU,KAAK,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC;YACrD,IAAA,iCAAoB,EAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;YAEvD,QAAQ,CAAC,IAAI,CACX,yBAAyB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,CAAC,CACxE,CAAC;YAEF,MAAM,KAAK,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,cAAc,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,QAAQ,CAAC,IAAI,CACX,QAAQ,OAAO,GAAG,QAAQ,KAAK,IAAA,6BAAgB,EAAC,UAAU,CAAC,OAAO,KAAK,EAAE,CAC1E,CAAC;YACF,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,cAAc,EAAE,CAAC,CAAC;QAC/C,CAAC;;YACC,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,IAAA,6BAAgB,EAAC,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;KACpE,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"vector.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAe,MAAM,iBAAiB,CAAC;AAM9D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;;IAOzB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,CAAC,EAAE,MAAM,CAAC;QACV,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAwBhB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,CAAC,EAAE,MAAM,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAyChB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAgB1B"}
1
+ {"version":3,"file":"vector.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAe,MAAM,iBAAiB,CAAC;AAM9D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;;IAOzB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,CAAC,EAAE,MAAM,CAAC;QACV,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IAwBhB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,CAAC,EAAE,MAAM,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAClC,GAAG,YAAY;IA2ChB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;CAgB1B"}
@@ -61,8 +61,10 @@ export class VectorCompiler {
61
61
  const providerParam = `v_provider_${suffix}`;
62
62
  const providerCfgParam = `v_providerConfig_${suffix}`;
63
63
  const encodedVar = `__v_encoded_${suffix}`;
64
+ // `genai.vector.encode` is a FUNCTION (only `encodeBatch` is a
65
+ // procedure), so it is evaluated in a WITH, not CALLed.
64
66
  const cypher = [
65
- `CALL genai.vector.encode($${phraseParam}, $${providerParam}, $${providerCfgParam}) YIELD vector AS ${encodedVar}`,
67
+ `WITH genai.vector.encode($${phraseParam}, $${providerParam}, $${providerCfgParam}) AS ${encodedVar}`,
66
68
  `CALL db.index.vector.queryNodes($${nameParam}, $${kParam}, ${encodedVar}) YIELD node AS n, score`,
67
69
  ].join('\n');
68
70
  const params = {
@@ -1 +1 @@
1
- {"version":3,"file":"vector.compiler.js","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vector.compiler.js","sourceRoot":"","sources":["../../../src/compilers/vector.compiler.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,20 @@
1
1
  import type { PropertyDefinition } from '../schema/types';
2
2
  /**
3
- * Builds the `CALL { ... }` subquery that projects a `@cypher` field. Same
4
- * shape as the v1.5.0 sort prelude — `this` is rebound from the outer node
5
- * variable inside the subquery, no text substitution.
3
+ * Builds the `CALL { ... }` subquery that projects a `@cypher` field (used
4
+ * by the SELECT, WHERE and sort preludes). `this` is rebound from the
5
+ * outer node variable inside the subquery, no text substitution.
6
+ *
7
+ * Row-preserving: the user's statement runs in an inner CALL and its
8
+ * `columnName` column is reduced with `head(collect(...))`. A grouping-
9
+ * free aggregation always yields exactly ONE row, so the outer row is
10
+ * kept with `null` when the statement returns no rows, and kept once
11
+ * (first value) when it returns several — matching the nested
12
+ * `head(COLLECT { ... })` projection. Pre-2.4.0 the statement was CALLed
13
+ * directly, which dropped the node on zero rows and duplicated it on many.
14
+ * Works on every Neo4j 5.x (unlike `OPTIONAL CALL`, 5.24+) and still lets
15
+ * the statement return extra columns (unlike `COLLECT { }`).
6
16
  */
7
- export declare function buildCypherFieldCall(statement: string, nodeVar: string): string;
17
+ export declare function buildCypherFieldCall(statement: string, nodeVar: string, columnName: string): string;
8
18
  /**
9
19
  * Builds an inline `head(COLLECT { ... })` subquery expression for a
10
20
  * `@cypher` scalar field. Used inside contexts where a CALL prelude cannot
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-field-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAQR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAWzB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAfjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;;IAG7C,sEAAsE;IACrD,OAAO,EAAE,MAAM;IAChC,2DAA2D;IAC1C,YAAY,GAAE,aAAa,CAAC,MAAM,CAAM;IACzD,4DAA4D;IAC3C,cAAc,GAAE,MAAe;IAKlD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM;IAiChE,+CAA+C;IAC/C,MAAM,IAAI,OAAO;IAIjB,sEAAsE;IACtE,IAAI,IAAI,MAAM,EAAE;IAIhB,wDAAwD;IACxD,OAAO,IAAI,MAAM,EAAE;IAInB,0CAA0C;IAC1C,UAAU,IAAI,MAAM;CAGrB"}
1
+ {"version":3,"file":"cypher-field-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAaR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAWzB,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAfjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;;IAG7C,sEAAsE;IACrD,OAAO,EAAE,MAAM;IAChC,2DAA2D;IAC1C,YAAY,GAAE,aAAa,CAAC,MAAM,CAAM;IACzD,4DAA4D;IAC3C,cAAc,GAAE,MAAe;IAKlD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM;IAiChE,+CAA+C;IAC/C,MAAM,IAAI,OAAO;IAIjB,sEAAsE;IACtE,IAAI,IAAI,MAAM,EAAE;IAIhB,wDAAwD;IACxD,OAAO,IAAI,MAAM,EAAE;IAInB,0CAA0C;IAC1C,UAAU,IAAI,MAAM;CAGrB"}
@@ -1,15 +1,30 @@
1
1
  import { assertSafeIdentifier, escapeIdentifier } from './validation';
2
2
  /**
3
- * Builds the `CALL { ... }` subquery that projects a `@cypher` field. Same
4
- * shape as the v1.5.0 sort prelude — `this` is rebound from the outer node
5
- * variable inside the subquery, no text substitution.
3
+ * Builds the `CALL { ... }` subquery that projects a `@cypher` field (used
4
+ * by the SELECT, WHERE and sort preludes). `this` is rebound from the
5
+ * outer node variable inside the subquery, no text substitution.
6
+ *
7
+ * Row-preserving: the user's statement runs in an inner CALL and its
8
+ * `columnName` column is reduced with `head(collect(...))`. A grouping-
9
+ * free aggregation always yields exactly ONE row, so the outer row is
10
+ * kept with `null` when the statement returns no rows, and kept once
11
+ * (first value) when it returns several — matching the nested
12
+ * `head(COLLECT { ... })` projection. Pre-2.4.0 the statement was CALLed
13
+ * directly, which dropped the node on zero rows and duplicated it on many.
14
+ * Works on every Neo4j 5.x (unlike `OPTIONAL CALL`, 5.24+) and still lets
15
+ * the statement return extra columns (unlike `COLLECT { }`).
6
16
  */
7
- export function buildCypherFieldCall(statement, nodeVar) {
17
+ export function buildCypherFieldCall(statement, nodeVar, columnName) {
18
+ const col = escapeIdentifier(columnName);
8
19
  return [
9
20
  `CALL {`,
10
21
  ` WITH ${nodeVar}`,
11
- ` WITH ${nodeVar} AS this`,
12
- ` ${statement}`,
22
+ ` CALL {`,
23
+ ` WITH ${nodeVar}`,
24
+ ` WITH ${nodeVar} AS this`,
25
+ ` ${statement}`,
26
+ ` }`,
27
+ ` RETURN head(collect(${col})) AS ${col}`,
13
28
  `}`,
14
29
  ].join('\n');
15
30
  }
@@ -89,7 +104,7 @@ export class CypherFieldScope {
89
104
  assertSafeIdentifier(alias, '@cypher alias');
90
105
  const carry = [...this.preserveVars, ...this.carriedAliases];
91
106
  const carryStr = carry.length ? `, ${carry.join(', ')}` : '';
92
- this.callLines.push(buildCypherFieldCall(propDef.cypherStatement, this.nodeVar));
107
+ this.callLines.push(buildCypherFieldCall(propDef.cypherStatement, this.nodeVar, columnName));
93
108
  this.callLines.push(`WITH ${this.nodeVar}${carryStr}, ${escapeIdentifier(columnName)} AS ${alias}`);
94
109
  this.carriedAliases.push(alias);
95
110
  this.aliases.set(fieldName, alias);
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-field-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cypher-field-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-field-projection.ts"],"names":[],"mappings":"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"}
@@ -1,23 +1,16 @@
1
1
  import type { PropertyDefinition } from '../schema/types';
2
2
  /**
3
3
  * Builds the `CALL { ... }` subquery used to project an `@cypher` field
4
- * for `ORDER BY`. The user's statement is embedded verbatim with `this`
5
- * rebound from the outer node variable — no text substitution.
4
+ * for `ORDER BY` — the same row-preserving shape as the SELECT / WHERE
5
+ * preludes (see `buildCypherFieldCall`): a node whose statement returns
6
+ * no rows sorts with `null` instead of vanishing, and one returning
7
+ * several rows sorts once.
6
8
  *
7
9
  * The caller is expected to follow this CALL with its own `WITH` clause
8
10
  * to rename the projected column (`<columnName>`) to a unique alias
9
11
  * (e.g. `__sort_<fieldName>`) and carry forward any prior sort aliases.
10
- *
11
- * Example output:
12
- * ```cypher
13
- * CALL {
14
- * WITH n
15
- * WITH n AS this
16
- * MATCH (this)-[:HAS_STATUS]->(s) RETURN s.name AS statusName
17
- * }
18
- * ```
19
12
  */
20
- export declare function buildCypherSortProjection(statement: string, nodeVar: string): string;
13
+ export declare function buildCypherSortProjection(statement: string, nodeVar: string, columnName: string): string;
21
14
  /**
22
15
  * Compiles a `sort` array (mixed stored-field + `@cypher`-field entries)
23
16
  * into the Cypher fragments needed before and after the `RETURN` clause.
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-sort-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAS1D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAQR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAClE,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDnC"}
1
+ {"version":3,"file":"cypher-sort-projection.d.ts","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAU1D;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAClE,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDnC"}
@@ -1,30 +1,18 @@
1
+ import { buildCypherFieldCall } from './cypher-field-projection';
1
2
  import { assertPlainObject, assertSafeIdentifier, assertSingleSortKey, assertSortDirection, escapeIdentifier, } from './validation';
2
3
  /**
3
4
  * Builds the `CALL { ... }` subquery used to project an `@cypher` field
4
- * for `ORDER BY`. The user's statement is embedded verbatim with `this`
5
- * rebound from the outer node variable — no text substitution.
5
+ * for `ORDER BY` — the same row-preserving shape as the SELECT / WHERE
6
+ * preludes (see `buildCypherFieldCall`): a node whose statement returns
7
+ * no rows sorts with `null` instead of vanishing, and one returning
8
+ * several rows sorts once.
6
9
  *
7
10
  * The caller is expected to follow this CALL with its own `WITH` clause
8
11
  * to rename the projected column (`<columnName>`) to a unique alias
9
12
  * (e.g. `__sort_<fieldName>`) and carry forward any prior sort aliases.
10
- *
11
- * Example output:
12
- * ```cypher
13
- * CALL {
14
- * WITH n
15
- * WITH n AS this
16
- * MATCH (this)-[:HAS_STATUS]->(s) RETURN s.name AS statusName
17
- * }
18
- * ```
19
13
  */
20
- export function buildCypherSortProjection(statement, nodeVar) {
21
- return [
22
- `CALL {`,
23
- ` WITH ${nodeVar}`,
24
- ` WITH ${nodeVar} AS this`,
25
- ` ${statement}`,
26
- `}`,
27
- ].join('\n');
14
+ export function buildCypherSortProjection(statement, nodeVar, columnName) {
15
+ return buildCypherFieldCall(statement, nodeVar, columnName);
28
16
  }
29
17
  /**
30
18
  * Compiles a `sort` array (mixed stored-field + `@cypher`-field entries)
@@ -69,7 +57,7 @@ export function compileSortClause(args) {
69
57
  const alias = `__sort_${field}`;
70
58
  const columnName = propDef.cypherColumnName ?? field;
71
59
  assertSafeIdentifier(columnName, '@cypher columnName');
72
- preLines.push(buildCypherSortProjection(propDef.cypherStatement, nodeVar));
60
+ preLines.push(buildCypherSortProjection(propDef.cypherStatement, nodeVar, columnName));
73
61
  const carry = [...preserveVars, ...carriedAliases];
74
62
  const carryStr = carry.length ? `, ${carry.join(', ')}` : '';
75
63
  preLines.push(`WITH ${nodeVar}${carryStr}, ${escapeIdentifier(columnName)} AS ${alias}`);
@@ -1 +1 @@
1
- {"version":3,"file":"cypher-sort-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cypher-sort-projection.js","sourceRoot":"","sources":["../../../src/utils/cypher-sort-projection.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grafeo-ogm",
3
- "version": "2.3.5",
3
+ "version": "2.4.0",
4
4
  "description": "Type-safe Neo4j ORM / OGM for TypeScript. Define your graph in GraphQL SDL, get fully typed Prisma-like CRUD, optimized Cypher, and zero-config code generation. Community successor to @neo4j/graphql-ogm.",
5
5
  "license": "MIT",
6
6
  "author": "Alejandro Guzman",