falkordb 6.9.2 → 6.9.3
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/README.md +56 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +11 -1
- package/dist/src/clients/client.d.ts +23 -5
- package/dist/src/clients/client.js +7 -0
- package/dist/src/clients/cluster.d.ts +16 -6
- package/dist/src/clients/cluster.js +41 -16
- package/dist/src/clients/nullClient.d.ts +4 -3
- package/dist/src/clients/nullClient.js +5 -2
- package/dist/src/clients/single.d.ts +6 -5
- package/dist/src/clients/single.js +17 -8
- package/dist/src/commands/CONSTRAINT_CREATE.js +3 -1
- package/dist/src/commands/CONSTRAINT_DROP.js +3 -1
- package/dist/src/commands/COPY.js +3 -1
- package/dist/src/commands/EXPLAIN.d.ts +3 -2
- package/dist/src/commands/EXPLAIN.js +5 -4
- package/dist/src/commands/MEMORY_USAGE.js +7 -4
- package/dist/src/commands/PROFILE.d.ts +4 -3
- package/dist/src/commands/PROFILE.js +7 -5
- package/dist/src/commands/QUERY.js +7 -2
- package/dist/src/commands/RO_QUERY.js +5 -1
- package/dist/src/commands/SLOWLOG.d.ts +1 -1
- package/dist/src/commands/SLOWLOG.js +3 -1
- package/dist/src/commands/SLOWLOG_RESET.d.ts +5 -0
- package/dist/src/commands/SLOWLOG_RESET.js +19 -0
- package/dist/src/commands/index.d.ts +10 -1
- package/dist/src/commands/index.js +60 -12
- package/dist/src/entities.d.ts +19 -0
- package/dist/src/entities.js +121 -0
- package/dist/src/execution-plan.d.ts +45 -0
- package/dist/src/execution-plan.js +121 -0
- package/dist/src/falkordb.js +31 -4
- package/dist/src/graph.d.ts +95 -18
- package/dist/src/graph.js +321 -75
- package/dist/src/query-statistics.d.ts +6 -0
- package/dist/src/query-statistics.js +66 -0
- package/dist/src/types/falkordb-options.d.ts +8 -0
- package/dist/src/types/graph-value.d.ts +11 -5
- package/dist/src/types/index.d.ts +2 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/procedures.d.ts +47 -0
- package/dist/src/types/procedures.js +2 -0
- package/dist/src/types/query-options.d.ts +6 -1
- package/dist/src/types/query-statistics.d.ts +20 -0
- package/dist/src/types/query-statistics.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
`falkordb` is a [FalkorDB](https://www.falkordb.com) client for Node.js.
|
|
12
12
|
|
|
13
|
+
> **Upgrading from v6?** Version 7 has breaking changes; see the [migration guide](MIGRATION.md).
|
|
14
|
+
|
|
13
15
|
## Installation
|
|
14
16
|
|
|
15
17
|
Start a falkordb via docker:
|
|
@@ -50,7 +52,9 @@ const result = await graph.query(`MATCH (r:Rider)-[:rides]->(t:Team)
|
|
|
50
52
|
WHERE t.name = $name RETURN r.name`,
|
|
51
53
|
{params: {name: 'Yamaha'}})
|
|
52
54
|
|
|
53
|
-
console.log(result)
|
|
55
|
+
console.log(result.data) // [{ 'r.name': 'Valentino Rossi' }]
|
|
56
|
+
console.log(result.headers) // ['r.name']
|
|
57
|
+
console.log(result.stats) // { nodesCreated: 0, ..., cachedExecution: false, queryInternalExecutionTime: 0.31 }
|
|
54
58
|
|
|
55
59
|
console.log(await db.list())
|
|
56
60
|
console.log(await db.info())
|
|
@@ -60,6 +64,57 @@ db.close()
|
|
|
60
64
|
|
|
61
65
|
To learn more about Cypher query language check: https://docs.falkordb.com/cypher/
|
|
62
66
|
|
|
67
|
+
### Query Parameters
|
|
68
|
+
|
|
69
|
+
Parameter values can be a `string`, a finite `number`, a `bigint`, a `boolean`, `null`, an array, a typed array
|
|
70
|
+
(e.g. a `Float32Array` vector, sent as a list) or a plain object (sent as a map). Names that are not plain
|
|
71
|
+
identifiers, such as `my-key` or `@type`, work too: quote them in the query, e.g. `` $`my-key` ``.
|
|
72
|
+
An empty name, or one containing the `` ` `` character, throws a `TypeError`, since FalkorDB cannot
|
|
73
|
+
represent it.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
await graph.query('RETURN $`my-key`, $vec', {params: {'my-key': 1, vec: new Float32Array([0.1, 0.2])}})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
A plain object is an object literal or one made with `Object.create(null)`. Any other object, such as a
|
|
80
|
+
class instance, `Date`, `Map` or `Set`, throws a `TypeError`, as do `undefined` and `NaN`; convert such
|
|
81
|
+
values first:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
await graph.query('CREATE (:User $props)', {params: {props: {...user, createdAt: user.createdAt.toISOString()}}})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
A `bigint` is sent exactly. Integers in query results are returned as a `number` by default, so values beyond
|
|
88
|
+
`Number.MAX_SAFE_INTEGER` come back rounded; see [Large Integers](#large-integers) to read them exactly.
|
|
89
|
+
|
|
90
|
+
### Large Integers
|
|
91
|
+
|
|
92
|
+
To read every integer in query results exactly, connect with `integers: 'bigint'`. Integer values then come
|
|
93
|
+
back as a `bigint`, including small ones; node and edge ids stay a `number`.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const db = await FalkorDB.connect({ socket: { host: 'localhost', port: 6379 }, integers: 'bigint' })
|
|
97
|
+
const { data } = await db.selectGraph('g').query('RETURN 9007199254740993 AS n')
|
|
98
|
+
console.log(data) // [{ n: 9007199254740993n }]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`JSON.stringify` throws on a `bigint`, so convert such values before serializing them.
|
|
102
|
+
|
|
103
|
+
### Query Replies
|
|
104
|
+
|
|
105
|
+
`graph.query`, `graph.roQuery` and the index helpers (such as `graph.createNodeRangeIndex`) resolve to `{ headers?, data?, stats }`:
|
|
106
|
+
`headers` and `data` are present when the query returns columns, and `stats` always holds the server's statistics as numbers (a counter the server did not report is `0`).
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const { stats } = await graph.query(`CREATE (:Rider {name:'Jorge Lorenzo'})`)
|
|
110
|
+
|
|
111
|
+
console.log(stats.nodesCreated) // 1
|
|
112
|
+
console.log(stats.queryInternalExecutionTime) // milliseconds, e.g. 0.42
|
|
113
|
+
console.log(stats.cachedExecution) // false
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Version 7 removed the raw `metadata` lines (such as `"Nodes created: 1"`) from these replies; read the matching `stats` field instead.
|
|
117
|
+
|
|
63
118
|
### Connection Options
|
|
64
119
|
|
|
65
120
|
`host` and `port` are the shorthand for a plain TCP connection and default to `localhost:6379`.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,9 @@ export { Graph } from './src/graph';
|
|
|
2
2
|
export { ConstraintType, EntityType } from './src/enums';
|
|
3
3
|
export { FalkorDB } from './src/falkordb';
|
|
4
4
|
export type { FalkorDBOptions } from './src/types';
|
|
5
|
-
export type {
|
|
5
|
+
export type { GraphReply, QueryStatistics } from './src/types';
|
|
6
|
+
export { ExecutionPlan, Operation } from './src/execution-plan';
|
|
7
|
+
export { nodeToString, edgeToString, pathToString, nodesEqual, edgesEqual, pathsEqual } from './src/entities';
|
|
8
|
+
export type { GraphNode, GraphEdge, GraphPath, GraphValue } from './src/types';
|
|
9
|
+
export type { QueryParam, QueryParams, QueryOptions, QueryOptionsBackwardCompatible, PlanOptions } from './src/types';
|
|
10
|
+
export type { CallProcedureOptions, ConstraintInfo, IndexInfo, VectorIndexOptions } from './src/types';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FalkorDB = exports.EntityType = exports.ConstraintType = exports.Graph = void 0;
|
|
3
|
+
exports.pathsEqual = exports.edgesEqual = exports.nodesEqual = exports.pathToString = exports.edgeToString = exports.nodeToString = exports.Operation = exports.ExecutionPlan = exports.FalkorDB = exports.EntityType = exports.ConstraintType = exports.Graph = void 0;
|
|
4
4
|
// Named re-exports, not `default as`: with esModuleInterop (always on since
|
|
5
5
|
// TypeScript 6) a default re-export compiles to `__importDefault(m).default`,
|
|
6
6
|
// which Node's CommonJS export detection cannot see, so ESM callers could not
|
|
@@ -12,3 +12,13 @@ Object.defineProperty(exports, "ConstraintType", { enumerable: true, get: functi
|
|
|
12
12
|
Object.defineProperty(exports, "EntityType", { enumerable: true, get: function () { return enums_1.EntityType; } });
|
|
13
13
|
var falkordb_1 = require("./src/falkordb");
|
|
14
14
|
Object.defineProperty(exports, "FalkorDB", { enumerable: true, get: function () { return falkordb_1.FalkorDB; } });
|
|
15
|
+
var execution_plan_1 = require("./src/execution-plan");
|
|
16
|
+
Object.defineProperty(exports, "ExecutionPlan", { enumerable: true, get: function () { return execution_plan_1.ExecutionPlan; } });
|
|
17
|
+
Object.defineProperty(exports, "Operation", { enumerable: true, get: function () { return execution_plan_1.Operation; } });
|
|
18
|
+
var entities_1 = require("./src/entities");
|
|
19
|
+
Object.defineProperty(exports, "nodeToString", { enumerable: true, get: function () { return entities_1.nodeToString; } });
|
|
20
|
+
Object.defineProperty(exports, "edgeToString", { enumerable: true, get: function () { return entities_1.edgeToString; } });
|
|
21
|
+
Object.defineProperty(exports, "pathToString", { enumerable: true, get: function () { return entities_1.pathToString; } });
|
|
22
|
+
Object.defineProperty(exports, "nodesEqual", { enumerable: true, get: function () { return entities_1.nodesEqual; } });
|
|
23
|
+
Object.defineProperty(exports, "edgesEqual", { enumerable: true, get: function () { return entities_1.edgesEqual; } });
|
|
24
|
+
Object.defineProperty(exports, "pathsEqual", { enumerable: true, get: function () { return entities_1.pathsEqual; } });
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { RedisArgument } from "@redis/client";
|
|
2
2
|
import { ConstraintType, EntityType } from "../enums";
|
|
3
3
|
import FalkorDB from "../falkordb";
|
|
4
|
-
import type { MemoryUsageOptions, MemoryUsageReply, QueryOptions, SingleGraphConnection, SlowLogReply, UdfListReply } from "../types";
|
|
4
|
+
import type { MemoryUsageOptions, MemoryUsageReply, PlanOptions, QueryOptions, SingleGraphConnection, SlowLogReply, UdfListReply } from "../types";
|
|
5
|
+
/**
|
|
6
|
+
* Returns integer replies as their exact digits, for graphs whose integers
|
|
7
|
+
* are read as `bigint`: a `number` would round any beyond 2^53.
|
|
8
|
+
*/
|
|
9
|
+
export declare const EXACT_INTEGERS: {
|
|
10
|
+
readonly 58: StringConstructor;
|
|
11
|
+
};
|
|
5
12
|
export interface Client {
|
|
6
13
|
init(falkordb: FalkorDB): Promise<void>;
|
|
7
14
|
list(): Promise<Array<string>>;
|
|
@@ -16,14 +23,25 @@ export interface Client {
|
|
|
16
23
|
configGet(configKey: string): Promise<(string | number)[] | (string | number)[][]>;
|
|
17
24
|
configSet(configKey: string, value: number | string): Promise<void>;
|
|
18
25
|
info(section?: string): Promise<(string | string[])[]>;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @param exactIntegers Return integer replies as strings of their exact
|
|
28
|
+
* digits (see `EXACT_INTEGERS`)
|
|
29
|
+
*/
|
|
30
|
+
query<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, exactIntegers?: boolean): Promise<any>;
|
|
31
|
+
profile<T>(graph: string, query: RedisArgument, options?: PlanOptions): Promise<any>;
|
|
32
|
+
/**
|
|
33
|
+
* @param primary Run on the graph's master even where reads may be served
|
|
34
|
+
* by replicas, for a reply that must be at least as new as the master's
|
|
35
|
+
* @param exactIntegers Return integer replies as strings of their exact
|
|
36
|
+
* digits (see `EXACT_INTEGERS`)
|
|
37
|
+
*/
|
|
38
|
+
roQuery<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, primary?: boolean, exactIntegers?: boolean): Promise<any>;
|
|
22
39
|
copy<T>(srcGraph: string, destGraph: string): Promise<any>;
|
|
23
40
|
delete(graph: string): Promise<void>;
|
|
24
|
-
explain(graph: string, query: string): Promise<any>;
|
|
41
|
+
explain(graph: string, query: string, options?: PlanOptions): Promise<any>;
|
|
25
42
|
memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
|
|
26
43
|
slowLog(graph: string): Promise<SlowLogReply>;
|
|
44
|
+
slowLogReset(graph: string): Promise<void>;
|
|
27
45
|
constraintCreate(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
28
46
|
constraintDrop(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
29
47
|
udfLoad(name: string, script: string | Function, replace?: boolean): Promise<string>;
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXACT_INTEGERS = void 0;
|
|
4
|
+
const client_1 = require("@redis/client");
|
|
5
|
+
/**
|
|
6
|
+
* Returns integer replies as their exact digits, for graphs whose integers
|
|
7
|
+
* are read as `bigint`: a `number` would round any beyond 2^53.
|
|
8
|
+
*/
|
|
9
|
+
exports.EXACT_INTEGERS = { [client_1.RESP_TYPES.NUMBER]: String };
|
|
@@ -3,19 +3,28 @@ import { ConstraintType, EntityType } from "../enums";
|
|
|
3
3
|
import { RedisArgument, RedisFunctions, RedisScripts } from "@redis/client";
|
|
4
4
|
import commands from "../commands";
|
|
5
5
|
import FalkorDB from "../falkordb";
|
|
6
|
-
import type { ClusterGraphConnection, MemoryUsageOptions, MemoryUsageReply, QueryOptions, SingleGraphConnection, UdfListReply } from "../types";
|
|
6
|
+
import type { ClusterGraphConnection, MemoryUsageOptions, MemoryUsageReply, PlanOptions, QueryOptions, SingleGraphConnection, UdfListReply } from "../types";
|
|
7
7
|
export type { ClusterGraphConnection };
|
|
8
|
+
export interface ClusterOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Serve read-only commands (e.g. `GRAPH.RO_QUERY`) from replicas as well as
|
|
11
|
+
* masters. Replica connections are sent
|
|
12
|
+
* [`READONLY`](https://redis.io/docs/latest/commands/readonly/) so they
|
|
13
|
+
* answer reads instead of redirecting them; writes still go to the masters.
|
|
14
|
+
*/
|
|
15
|
+
useReplicas?: boolean;
|
|
16
|
+
}
|
|
8
17
|
/**
|
|
9
18
|
* A client that connects to a Redis Cluster.
|
|
10
19
|
*/
|
|
11
20
|
export declare class Cluster implements Client {
|
|
12
21
|
#private;
|
|
13
|
-
constructor(client: SingleGraphConnection);
|
|
22
|
+
constructor(client: SingleGraphConnection, { useReplicas }?: ClusterOptions);
|
|
14
23
|
getConnection(): Promise<import("@redis/client").RedisClientType<{
|
|
15
24
|
falkordb: typeof commands;
|
|
16
25
|
}, RedisFunctions, RedisScripts, 2, {}>>;
|
|
17
26
|
init(falkordb: FalkorDB): Promise<void>;
|
|
18
|
-
query<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number): Promise<{
|
|
27
|
+
query<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, exactIntegers?: boolean): Promise<{
|
|
19
28
|
headers: undefined;
|
|
20
29
|
data: undefined;
|
|
21
30
|
metadata: string[];
|
|
@@ -24,7 +33,7 @@ export declare class Cluster implements Client {
|
|
|
24
33
|
data: (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[];
|
|
25
34
|
metadata: string[];
|
|
26
35
|
}>;
|
|
27
|
-
roQuery<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number): Promise<{
|
|
36
|
+
roQuery<T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, primary?: boolean, exactIntegers?: boolean): Promise<{
|
|
28
37
|
headers: undefined;
|
|
29
38
|
data: undefined;
|
|
30
39
|
metadata: string[];
|
|
@@ -34,7 +43,7 @@ export declare class Cluster implements Client {
|
|
|
34
43
|
metadata: string[];
|
|
35
44
|
}>;
|
|
36
45
|
delete(graph: string): Promise<void>;
|
|
37
|
-
explain(graph: string, query: string): Promise<string[]>;
|
|
46
|
+
explain(graph: string, query: string, options?: PlanOptions): Promise<string[]>;
|
|
38
47
|
list(): Promise<Array<string>>;
|
|
39
48
|
stubs(): Promise<Array<string>>;
|
|
40
49
|
configGet(configKey: string): Promise<(string | number)[][] | (string | number)[]>;
|
|
@@ -47,6 +56,7 @@ export declare class Cluster implements Client {
|
|
|
47
56
|
query: string;
|
|
48
57
|
took: number;
|
|
49
58
|
}[]>;
|
|
59
|
+
slowLogReset(graph: string): Promise<void>;
|
|
50
60
|
memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
|
|
51
61
|
constraintCreate(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
52
62
|
constraintDrop(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
@@ -54,7 +64,7 @@ export declare class Cluster implements Client {
|
|
|
54
64
|
udfList(lib?: string, withCode?: boolean): Promise<UdfListReply>;
|
|
55
65
|
udfFlush(): Promise<string>;
|
|
56
66
|
udfDelete(lib: string): Promise<string>;
|
|
57
|
-
profile<_T>(graph: string, query: string): Promise<string[]>;
|
|
67
|
+
profile<_T>(graph: string, query: string, options?: PlanOptions): Promise<string[]>;
|
|
58
68
|
quit(): Promise<void>;
|
|
59
69
|
disconnect(): Promise<void>;
|
|
60
70
|
}
|
|
@@ -34,14 +34,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.Cluster = void 0;
|
|
37
|
-
const client_1 = require("
|
|
37
|
+
const client_1 = require("./client");
|
|
38
|
+
const RO_QUERY = __importStar(require("../commands/RO_QUERY"));
|
|
39
|
+
const client_2 = require("@redis/client");
|
|
38
40
|
const lodash = __importStar(require("lodash"));
|
|
39
41
|
/**
|
|
40
42
|
* A client that connects to a Redis Cluster.
|
|
41
43
|
*/
|
|
42
44
|
class Cluster {
|
|
43
45
|
#client;
|
|
44
|
-
constructor(client) {
|
|
46
|
+
constructor(client, { useReplicas = false } = {}) {
|
|
45
47
|
// Convert the single client options to a cluster client options
|
|
46
48
|
const redisClusterOption = client.options;
|
|
47
49
|
redisClusterOption.rootNodes = [
|
|
@@ -52,11 +54,19 @@ class Cluster {
|
|
|
52
54
|
defaults?.url && delete defaults.url;
|
|
53
55
|
redisClusterOption.defaults = defaults;
|
|
54
56
|
redisClusterOption.maxCommandRedirections = 100000;
|
|
57
|
+
redisClusterOption.useReplicas = useReplicas;
|
|
55
58
|
client.disconnect();
|
|
56
|
-
this.#client = (0,
|
|
59
|
+
this.#client = (0, client_2.createCluster)(redisClusterOption);
|
|
57
60
|
}
|
|
58
61
|
async getConnection() {
|
|
59
|
-
|
|
62
|
+
return this.#masterClient();
|
|
63
|
+
}
|
|
64
|
+
// Keyless commands are routed to a random node, which can be a replica when
|
|
65
|
+
// `useReplicas` is on, so writes without a key are sent to a master instead.
|
|
66
|
+
async #masterClient() {
|
|
67
|
+
const { masters } = this.#client;
|
|
68
|
+
const master = masters[Math.floor(Math.random() * masters.length)];
|
|
69
|
+
const connection = this.#client.nodeClient(master);
|
|
60
70
|
return connection instanceof Promise ? await connection : connection;
|
|
61
71
|
}
|
|
62
72
|
async init(falkordb) {
|
|
@@ -65,19 +75,30 @@ class Cluster {
|
|
|
65
75
|
.connect();
|
|
66
76
|
}
|
|
67
77
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
68
|
-
async query(graph, query, options, compact = true, version) {
|
|
69
|
-
return this.#
|
|
78
|
+
async query(graph, query, options, compact = true, version, exactIntegers = false) {
|
|
79
|
+
return this.#withIntegers(exactIntegers).falkordb.query(graph, query, options, compact, version);
|
|
80
|
+
}
|
|
81
|
+
#withIntegers(exactIntegers) {
|
|
82
|
+
return exactIntegers ? this.#client.withTypeMapping(client_1.EXACT_INTEGERS) : this.#client;
|
|
70
83
|
}
|
|
71
84
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
72
|
-
async roQuery(graph, query, options, compact = true, version) {
|
|
73
|
-
|
|
85
|
+
async roQuery(graph, query, options, compact = true, version, primary = false, exactIntegers = false) {
|
|
86
|
+
if (primary) {
|
|
87
|
+
// Still GRAPH.RO_QUERY, so read-only users can run it, but routed to the
|
|
88
|
+
// slot's master as a write would be
|
|
89
|
+
const args = RO_QUERY.transformArguments(graph, query, options, compact, version);
|
|
90
|
+
return RO_QUERY.transformReply(exactIntegers
|
|
91
|
+
? await this.#client.sendCommand(graph, false, args, { typeMapping: client_1.EXACT_INTEGERS })
|
|
92
|
+
: await this.#client.sendCommand(graph, false, args));
|
|
93
|
+
}
|
|
94
|
+
return this.#withIntegers(exactIntegers).falkordb.roQuery(graph, query, options, compact, version);
|
|
74
95
|
}
|
|
75
96
|
async delete(graph) {
|
|
76
97
|
const reply = this.#client.falkordb.delete(graph);
|
|
77
98
|
return reply.then(() => { });
|
|
78
99
|
}
|
|
79
|
-
async explain(graph, query) {
|
|
80
|
-
return this.#client.falkordb.explain(graph, query);
|
|
100
|
+
async explain(graph, query, options) {
|
|
101
|
+
return this.#client.falkordb.explain(graph, query, options);
|
|
81
102
|
}
|
|
82
103
|
async list() {
|
|
83
104
|
const reply = await Promise.all(this.#client.masters.map(async (master) => {
|
|
@@ -120,7 +141,7 @@ class Cluster {
|
|
|
120
141
|
return this.#client.falkordb.configGet(configKey);
|
|
121
142
|
}
|
|
122
143
|
async configSet(configKey, value) {
|
|
123
|
-
const reply = this.#
|
|
144
|
+
const reply = (await this.#masterClient()).falkordb.configSet(configKey, value);
|
|
124
145
|
return reply.then(() => { });
|
|
125
146
|
}
|
|
126
147
|
async info(section) {
|
|
@@ -132,6 +153,10 @@ class Cluster {
|
|
|
132
153
|
slowLog(graph) {
|
|
133
154
|
return this.#client.falkordb.slowLog(graph);
|
|
134
155
|
}
|
|
156
|
+
async slowLogReset(graph) {
|
|
157
|
+
const reply = this.#client.falkordb.slowLogReset(graph);
|
|
158
|
+
return reply.then(() => { });
|
|
159
|
+
}
|
|
135
160
|
async memoryUsage(graph, options) {
|
|
136
161
|
return this.#client.falkordb.memoryUsage(graph, options);
|
|
137
162
|
}
|
|
@@ -144,19 +169,19 @@ class Cluster {
|
|
|
144
169
|
return reply.then(() => { });
|
|
145
170
|
}
|
|
146
171
|
async udfLoad(name, script, replace = false) {
|
|
147
|
-
return this.#
|
|
172
|
+
return (await this.#masterClient()).falkordb.udfLoad(name, script, replace);
|
|
148
173
|
}
|
|
149
174
|
async udfList(lib, withCode = false) {
|
|
150
175
|
return this.#client.falkordb.udfList(lib, withCode);
|
|
151
176
|
}
|
|
152
177
|
async udfFlush() {
|
|
153
|
-
return this.#
|
|
178
|
+
return (await this.#masterClient()).falkordb.udfFlush();
|
|
154
179
|
}
|
|
155
180
|
async udfDelete(lib) {
|
|
156
|
-
return this.#
|
|
181
|
+
return (await this.#masterClient()).falkordb.udfDelete(lib);
|
|
157
182
|
}
|
|
158
|
-
async profile(graph, query) {
|
|
159
|
-
return this.#client.falkordb.profile(graph, query);
|
|
183
|
+
async profile(graph, query, options) {
|
|
184
|
+
return this.#client.falkordb.profile(graph, query, options);
|
|
160
185
|
}
|
|
161
186
|
async quit() {
|
|
162
187
|
return this.disconnect();
|
|
@@ -2,7 +2,7 @@ import { RedisArgument } from "@redis/client";
|
|
|
2
2
|
import FalkorDB from "../falkordb";
|
|
3
3
|
import { ConstraintType, EntityType } from "../enums";
|
|
4
4
|
import { Client } from "./client";
|
|
5
|
-
import type { MemoryUsageOptions, MemoryUsageReply, QueryOptions, SingleGraphConnection, SlowLogReply, UdfListReply } from "../types";
|
|
5
|
+
import type { MemoryUsageOptions, MemoryUsageReply, PlanOptions, QueryOptions, SingleGraphConnection, SlowLogReply, UdfListReply } from "../types";
|
|
6
6
|
/**
|
|
7
7
|
* The `NullClient` class is a placeholder implementation of the `Client` interface.
|
|
8
8
|
*
|
|
@@ -23,12 +23,13 @@ export declare class NullClient implements Client {
|
|
|
23
23
|
configSet(_configKey: string, _value: number | string): Promise<void>;
|
|
24
24
|
info(_section?: string): Promise<(string | string[])[]>;
|
|
25
25
|
query<_T>(_graph: string, _query: RedisArgument, _options?: QueryOptions): Promise<any>;
|
|
26
|
-
profile<_T>(_graph: string, _query: RedisArgument): Promise<any>;
|
|
26
|
+
profile<_T>(_graph: string, _query: RedisArgument, _options?: PlanOptions): Promise<any>;
|
|
27
27
|
roQuery<_T>(_graph: string, _query: RedisArgument, _options?: QueryOptions): Promise<any>;
|
|
28
28
|
copy<_T>(_srcGraph: string, _destGraph: string): Promise<any>;
|
|
29
29
|
delete(_graph: string): Promise<void>;
|
|
30
|
-
explain(_graph: string, _query: string): Promise<any>;
|
|
30
|
+
explain(_graph: string, _query: string, _options?: PlanOptions): Promise<any>;
|
|
31
31
|
slowLog(_graph: string): Promise<SlowLogReply>;
|
|
32
|
+
slowLogReset(_graph: string): Promise<void>;
|
|
32
33
|
memoryUsage(_graph: string, _options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
|
|
33
34
|
constraintCreate(_graph: string, _constraintType: ConstraintType, _entityType: EntityType, _label: string, ..._properties: string[]): Promise<void>;
|
|
34
35
|
constraintDrop(_graph: string, _constraintType: ConstraintType, _entityType: EntityType, _label: string, ..._properties: string[]): Promise<void>;
|
|
@@ -37,7 +37,7 @@ class NullClient {
|
|
|
37
37
|
query(_graph, _query, _options) {
|
|
38
38
|
throw new Error("Method not implemented.");
|
|
39
39
|
}
|
|
40
|
-
profile(_graph, _query) {
|
|
40
|
+
profile(_graph, _query, _options) {
|
|
41
41
|
throw new Error("Method not implemented.");
|
|
42
42
|
}
|
|
43
43
|
roQuery(_graph, _query, _options) {
|
|
@@ -49,12 +49,15 @@ class NullClient {
|
|
|
49
49
|
delete(_graph) {
|
|
50
50
|
throw new Error("Method not implemented.");
|
|
51
51
|
}
|
|
52
|
-
explain(_graph, _query) {
|
|
52
|
+
explain(_graph, _query, _options) {
|
|
53
53
|
throw new Error("Method not implemented.");
|
|
54
54
|
}
|
|
55
55
|
slowLog(_graph) {
|
|
56
56
|
throw new Error("Method not implemented.");
|
|
57
57
|
}
|
|
58
|
+
slowLogReset(_graph) {
|
|
59
|
+
throw new Error("Method not implemented.");
|
|
60
|
+
}
|
|
58
61
|
memoryUsage(_graph, _options) {
|
|
59
62
|
throw new Error("Method not implemented.");
|
|
60
63
|
}
|
|
@@ -2,7 +2,7 @@ import { Client } from "./client";
|
|
|
2
2
|
import { ConstraintType, EntityType } from "../enums";
|
|
3
3
|
import { RedisArgument } from "@redis/client";
|
|
4
4
|
import FalkorDB from "../falkordb";
|
|
5
|
-
import type { MemoryUsageOptions, MemoryUsageReply, QueryOptions, SingleGraphConnection, UdfListReply } from "../types";
|
|
5
|
+
import type { MemoryUsageOptions, MemoryUsageReply, PlanOptions, QueryOptions, SingleGraphConnection, UdfListReply } from "../types";
|
|
6
6
|
export type { SingleGraphConnection };
|
|
7
7
|
export interface RunOptions {
|
|
8
8
|
/** The command does not change data, so running it twice is harmless */
|
|
@@ -17,7 +17,7 @@ export declare class Single implements Client {
|
|
|
17
17
|
* Subclasses override it to add recovery, e.g. retrying on a new master.
|
|
18
18
|
*/
|
|
19
19
|
protected run<T>(fn: (client: SingleGraphConnection) => Promise<T>, _options?: RunOptions): Promise<T>;
|
|
20
|
-
query<_T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number): Promise<{
|
|
20
|
+
query<_T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, exactIntegers?: boolean): Promise<{
|
|
21
21
|
headers: undefined;
|
|
22
22
|
data: undefined;
|
|
23
23
|
metadata: string[];
|
|
@@ -26,7 +26,7 @@ export declare class Single implements Client {
|
|
|
26
26
|
data: (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | (string | number | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[];
|
|
27
27
|
metadata: string[];
|
|
28
28
|
}>;
|
|
29
|
-
roQuery<_T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number): Promise<{
|
|
29
|
+
roQuery<_T>(graph: string, query: RedisArgument, options?: QueryOptions, compact?: boolean, version?: number, _primary?: boolean, exactIntegers?: boolean): Promise<{
|
|
30
30
|
headers: undefined;
|
|
31
31
|
data: undefined;
|
|
32
32
|
metadata: string[];
|
|
@@ -36,8 +36,8 @@ export declare class Single implements Client {
|
|
|
36
36
|
metadata: string[];
|
|
37
37
|
}>;
|
|
38
38
|
delete(graph: string): Promise<void>;
|
|
39
|
-
explain(graph: string, query: string): Promise<string[]>;
|
|
40
|
-
profile<_T>(graph: string, query: string): Promise<string[]>;
|
|
39
|
+
explain(graph: string, query: string, options?: PlanOptions): Promise<string[]>;
|
|
40
|
+
profile<_T>(graph: string, query: string, options?: PlanOptions): Promise<string[]>;
|
|
41
41
|
list(): Promise<string[]>;
|
|
42
42
|
stubs(): Promise<string[]>;
|
|
43
43
|
configGet(configKey: string): Promise<(string | number)[][] | (string | number)[]>;
|
|
@@ -49,6 +49,7 @@ export declare class Single implements Client {
|
|
|
49
49
|
query: string;
|
|
50
50
|
took: number;
|
|
51
51
|
}[]>;
|
|
52
|
+
slowLogReset(graph: string): Promise<void>;
|
|
52
53
|
memoryUsage(graph: string, options?: MemoryUsageOptions): Promise<MemoryUsageReply>;
|
|
53
54
|
constraintCreate(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
54
55
|
constraintDrop(graph: string, constraintType: ConstraintType, entityType: EntityType, label: string, ...properties: string[]): Promise<void>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Single = void 0;
|
|
4
|
+
const client_1 = require("./client");
|
|
4
5
|
const READ_ONLY = { readOnly: true };
|
|
6
|
+
function withIntegers(client, exactIntegers) {
|
|
7
|
+
return exactIntegers ? client.withTypeMapping(client_1.EXACT_INTEGERS) : client;
|
|
8
|
+
}
|
|
5
9
|
class Single {
|
|
6
10
|
client;
|
|
7
11
|
constructor(client) {
|
|
@@ -17,21 +21,22 @@ class Single {
|
|
|
17
21
|
run(fn, _options = {}) {
|
|
18
22
|
return fn(this.client);
|
|
19
23
|
}
|
|
20
|
-
async query(graph, query, options, compact = true, version) {
|
|
21
|
-
return await this.run((client) => client.falkordb.query(graph, query, options, compact, version));
|
|
24
|
+
async query(graph, query, options, compact = true, version, exactIntegers = false) {
|
|
25
|
+
return await this.run((client) => withIntegers(client, exactIntegers).falkordb.query(graph, query, options, compact, version));
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
// A single node serves every read, so `primary` needs no handling
|
|
28
|
+
async roQuery(graph, query, options, compact = true, version, _primary = false, exactIntegers = false) {
|
|
29
|
+
return await this.run((client) => withIntegers(client, exactIntegers).falkordb.roQuery(graph, query, options, compact, version), READ_ONLY);
|
|
25
30
|
}
|
|
26
31
|
async delete(graph) {
|
|
27
32
|
const reply = this.run((client) => client.falkordb.delete(graph));
|
|
28
33
|
return reply.then(() => { });
|
|
29
34
|
}
|
|
30
|
-
async explain(graph, query) {
|
|
31
|
-
return this.run((client) => client.falkordb.explain(graph, query), READ_ONLY);
|
|
35
|
+
async explain(graph, query, options) {
|
|
36
|
+
return this.run((client) => client.falkordb.explain(graph, query, options), READ_ONLY);
|
|
32
37
|
}
|
|
33
|
-
async profile(graph, query) {
|
|
34
|
-
return this.run((client) => client.falkordb.profile(graph, query));
|
|
38
|
+
async profile(graph, query, options) {
|
|
39
|
+
return this.run((client) => client.falkordb.profile(graph, query, options));
|
|
35
40
|
}
|
|
36
41
|
async list() {
|
|
37
42
|
return this.run((client) => client.falkordb.list(), READ_ONLY);
|
|
@@ -52,6 +57,10 @@ class Single {
|
|
|
52
57
|
async slowLog(graph) {
|
|
53
58
|
return this.run((client) => client.falkordb.slowLog(graph), READ_ONLY);
|
|
54
59
|
}
|
|
60
|
+
async slowLogReset(graph) {
|
|
61
|
+
const reply = this.run((client) => client.falkordb.slowLogReset(graph));
|
|
62
|
+
return reply.then(() => { });
|
|
63
|
+
}
|
|
55
64
|
async memoryUsage(graph, options) {
|
|
56
65
|
return this.run((client) => client.falkordb.memoryUsage(graph, options), READ_ONLY);
|
|
57
66
|
}
|
|
@@ -9,7 +9,9 @@ Object.defineProperty(exports, "ConstraintType", { enumerable: true, get: functi
|
|
|
9
9
|
Object.defineProperty(exports, "EntityType", { enumerable: true, get: function () { return enums_1.EntityType; } });
|
|
10
10
|
// GRAPH.CONSTRAINT CREATE key constraintType {NODE label | RELATIONSHIP reltype} PROPERTIES propCount prop [prop...]
|
|
11
11
|
function parseCommand(parser, key, constraintType, entityType, label, ...properties) {
|
|
12
|
-
parser.push('GRAPH.CONSTRAINT', 'CREATE'
|
|
12
|
+
parser.push('GRAPH.CONSTRAINT', 'CREATE');
|
|
13
|
+
parser.pushKey(key);
|
|
14
|
+
parser.push(constraintType, entityType, label, 'PROPERTIES', properties.length.toString(), ...properties);
|
|
13
15
|
}
|
|
14
16
|
function transformArguments(key, constraintType, entityType, label, ...properties) {
|
|
15
17
|
return [
|
|
@@ -5,7 +5,9 @@ exports.transformArguments = transformArguments;
|
|
|
5
5
|
exports.transformReply = transformReply;
|
|
6
6
|
// GRAPH.CONSTRAINT DROP key constraintType {NODE label | RELATIONSHIP reltype} PROPERTIES propCount prop [prop...]
|
|
7
7
|
function parseCommand(parser, key, constraintType, entityType, label, ...properties) {
|
|
8
|
-
parser.push('GRAPH.CONSTRAINT', 'DROP'
|
|
8
|
+
parser.push('GRAPH.CONSTRAINT', 'DROP');
|
|
9
|
+
parser.pushKey(key);
|
|
10
|
+
parser.push(constraintType, entityType, label, 'PROPERTIES', properties.length.toString(), ...properties);
|
|
9
11
|
}
|
|
10
12
|
function transformArguments(key, constraintType, entityType, label, ...properties) {
|
|
11
13
|
return [
|
|
@@ -4,7 +4,9 @@ exports.parseCommand = parseCommand;
|
|
|
4
4
|
exports.transformArguments = transformArguments;
|
|
5
5
|
exports.transformReply = transformReply;
|
|
6
6
|
function parseCommand(parser, srcGraph, destGraph) {
|
|
7
|
-
parser.push('GRAPH.COPY'
|
|
7
|
+
parser.push('GRAPH.COPY');
|
|
8
|
+
parser.pushKey(srcGraph);
|
|
9
|
+
parser.pushKey(destGraph);
|
|
8
10
|
}
|
|
9
11
|
function transformArguments(srcGraph, destGraph) {
|
|
10
12
|
return [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CommandParser } from '@redis/client';
|
|
2
|
+
import type { PlanOptions } from '../types';
|
|
2
3
|
export declare const FIRST_KEY_INDEX = 1;
|
|
3
4
|
export declare const IS_READ_ONLY = true;
|
|
4
|
-
export declare function parseCommand(parser: CommandParser, key: string, query: string): void;
|
|
5
|
-
export declare function transformArguments(key: string, query: string): Array<string>;
|
|
5
|
+
export declare function parseCommand(parser: CommandParser, key: string, query: string, options?: PlanOptions): void;
|
|
6
|
+
export declare function transformArguments(key: string, query: string, options?: PlanOptions): Array<string>;
|
|
6
7
|
export declare function transformReply(reply: unknown): Array<string>;
|
|
@@ -4,15 +4,16 @@ exports.IS_READ_ONLY = exports.FIRST_KEY_INDEX = void 0;
|
|
|
4
4
|
exports.parseCommand = parseCommand;
|
|
5
5
|
exports.transformArguments = transformArguments;
|
|
6
6
|
exports.transformReply = transformReply;
|
|
7
|
+
const _1 = require(".");
|
|
7
8
|
exports.FIRST_KEY_INDEX = 1;
|
|
8
9
|
exports.IS_READ_ONLY = true;
|
|
9
|
-
function parseCommand(parser, key, query) {
|
|
10
|
+
function parseCommand(parser, key, query, options) {
|
|
10
11
|
parser.push('GRAPH.EXPLAIN');
|
|
11
12
|
parser.pushKey(key);
|
|
12
|
-
parser.push(query);
|
|
13
|
+
parser.push((0, _1.withParamsHeader)(query, options?.params));
|
|
13
14
|
}
|
|
14
|
-
function transformArguments(key, query) {
|
|
15
|
-
return ['GRAPH.EXPLAIN', key, query];
|
|
15
|
+
function transformArguments(key, query, options) {
|
|
16
|
+
return ['GRAPH.EXPLAIN', key, (0, _1.withParamsHeader)(query, options?.params)];
|
|
16
17
|
}
|
|
17
18
|
function transformReply(reply) {
|
|
18
19
|
return reply;
|
|
@@ -4,14 +4,17 @@ exports.parseCommand = parseCommand;
|
|
|
4
4
|
exports.transformArguments = transformArguments;
|
|
5
5
|
exports.transformReply = transformReply;
|
|
6
6
|
function parseCommand(parser, key, options) {
|
|
7
|
-
parser.push("GRAPH.MEMORY", "USAGE"
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
parser.push("GRAPH.MEMORY", "USAGE");
|
|
8
|
+
parser.pushKey(key);
|
|
9
|
+
if (options?.SAMPLES !== undefined) {
|
|
10
|
+
parser.push("SAMPLES", String(options.SAMPLES));
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
function transformArguments(key, options) {
|
|
13
14
|
const args = ["GRAPH.MEMORY", "USAGE", key];
|
|
14
|
-
return options?.SAMPLES
|
|
15
|
+
return options?.SAMPLES !== undefined
|
|
16
|
+
? [...args, "SAMPLES", String(options.SAMPLES)]
|
|
17
|
+
: args;
|
|
15
18
|
}
|
|
16
19
|
function transformReply(reply) {
|
|
17
20
|
return reply;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CommandParser } from '@redis/client';
|
|
2
|
+
import type { PlanOptions } from '../types';
|
|
2
3
|
export declare const FIRST_KEY_INDEX = 1;
|
|
3
|
-
export declare const IS_READ_ONLY =
|
|
4
|
-
export declare function parseCommand(parser: CommandParser, key: string, query: string): void;
|
|
5
|
-
export declare function transformArguments(key: string, query: string): Array<string>;
|
|
4
|
+
export declare const IS_READ_ONLY = false;
|
|
5
|
+
export declare function parseCommand(parser: CommandParser, key: string, query: string, options?: PlanOptions): void;
|
|
6
|
+
export declare function transformArguments(key: string, query: string, options?: PlanOptions): Array<string>;
|
|
6
7
|
export declare function transformReply(reply: unknown): Array<string>;
|
|
@@ -4,15 +4,17 @@ exports.IS_READ_ONLY = exports.FIRST_KEY_INDEX = void 0;
|
|
|
4
4
|
exports.parseCommand = parseCommand;
|
|
5
5
|
exports.transformArguments = transformArguments;
|
|
6
6
|
exports.transformReply = transformReply;
|
|
7
|
+
const _1 = require(".");
|
|
7
8
|
exports.FIRST_KEY_INDEX = 1;
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
// PROFILE executes the query, which may write
|
|
10
|
+
exports.IS_READ_ONLY = false;
|
|
11
|
+
function parseCommand(parser, key, query, options) {
|
|
10
12
|
parser.push('GRAPH.PROFILE');
|
|
11
13
|
parser.pushKey(key);
|
|
12
|
-
parser.push(query);
|
|
14
|
+
parser.push((0, _1.withParamsHeader)(query, options?.params));
|
|
13
15
|
}
|
|
14
|
-
function transformArguments(key, query) {
|
|
15
|
-
return ['GRAPH.PROFILE', key, query];
|
|
16
|
+
function transformArguments(key, query, options) {
|
|
17
|
+
return ['GRAPH.PROFILE', key, (0, _1.withParamsHeader)(query, options?.params)];
|
|
16
18
|
}
|
|
17
19
|
function transformReply(reply) {
|
|
18
20
|
return reply;
|