diff --git a/.wordlist.txt b/.wordlist.txt index c8f58ed..5bc06b5 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -767,3 +767,28 @@ ORM orm OGM ogm +wikipedia +getStatistics +nodesCreated +ResponseError +JedisDataException +getMessage +FalkorDBError +eprintln +RunningQueries +WaitingQueries +helpText +sendCommand +setuser +userInfo +getuser +deluser +logEntries +substrings +timezones +deserialization +subnet +acl +elif +Ok +msg diff --git a/commands/acl.md b/commands/acl.md index 02b28a7..064c7d4 100644 --- a/commands/acl.md +++ b/commands/acl.md @@ -24,9 +24,37 @@ Usage: `ACL HELP` #### Example -``` -> ACL HELP -``` +{% capture shell_0 %} +ACL HELP +{% endcapture %} + +{% capture python_0 %} +from falkordb import FalkorDB +client = FalkorDB() +help_text = client.execute_command('ACL', 'HELP') +print(help_text) +{% endcapture %} + +{% capture javascript_0 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const helpText = await client.sendCommand(['ACL', 'HELP']); +console.log(helpText); +{% endcapture %} + +{% capture java_0 %} +FalkorDB client = new FalkorDB(); +Object helpText = client.sendCommand("ACL", "HELP"); +System.out.println(helpText); +{% endcapture %} + +{% capture rust_0 %} +let client = FalkorDB::connect_default(); +let help_text = client.execute_command(&["ACL", "HELP"])?; +println!("{:?}", help_text); +{% endcapture %} + +{% include code_tabs.html id="acl_help_tabs" shell=shell_0 python=python_0 javascript=javascript_0 java=java_0 rust=rust_0 %} #### Output @@ -55,9 +83,37 @@ Usage: `ACL SETUSER [rule1] [rule2] ...` #### Example -``` -> ACL SETUSER john on >password123 +GRAPH.LIST +GRAPH.RO_QUERY ~* -``` +{% capture shell_1 %} +ACL SETUSER john on >password123 +GRAPH.LIST +GRAPH.RO_QUERY ~* +{% endcapture %} + +{% capture python_1 %} +from falkordb import FalkorDB +client = FalkorDB() +result = client.execute_command('ACL', 'SETUSER', 'john', 'on', '>password123', '+GRAPH.LIST', '+GRAPH.RO_QUERY', '~*') +print(result) +{% endcapture %} + +{% capture javascript_1 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const result = await client.sendCommand(['ACL', 'SETUSER', 'john', 'on', '>password123', '+GRAPH.LIST', '+GRAPH.RO_QUERY', '~*']); +console.log(result); +{% endcapture %} + +{% capture java_1 %} +FalkorDB client = new FalkorDB(); +Object result = client.sendCommand("ACL", "SETUSER", "john", "on", ">password123", "+GRAPH.LIST", "+GRAPH.RO_QUERY", "~*"); +System.out.println(result); +{% endcapture %} + +{% capture rust_1 %} +let client = FalkorDB::connect_default(); +let result = client.execute_command(&["ACL", "SETUSER", "john", "on", ">password123", "+GRAPH.LIST", "+GRAPH.RO_QUERY", "~*"])?; +println!("{:?}", result); +{% endcapture %} + +{% include code_tabs.html id="setuser_tabs" shell=shell_1 python=python_1 javascript=javascript_1 java=java_1 rust=rust_1 %} ### ACL GETUSER @@ -68,9 +124,37 @@ Usage: `ACL GETUSER ` #### Example -``` -> ACL GETUSER john -``` +{% capture shell_2 %} +ACL GETUSER john +{% endcapture %} + +{% capture python_2 %} +from falkordb import FalkorDB +client = FalkorDB() +user_info = client.execute_command('ACL', 'GETUSER', 'john') +print(user_info) +{% endcapture %} + +{% capture javascript_2 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const userInfo = await client.sendCommand(['ACL', 'GETUSER', 'john']); +console.log(userInfo); +{% endcapture %} + +{% capture java_2 %} +FalkorDB client = new FalkorDB(); +Object userInfo = client.sendCommand("ACL", "GETUSER", "john"); +System.out.println(userInfo); +{% endcapture %} + +{% capture rust_2 %} +let client = FalkorDB::connect_default(); +let user_info = client.execute_command(&["ACL", "GETUSER", "john"])?; +println!("{:?}", user_info); +{% endcapture %} + +{% include code_tabs.html id="getuser_tabs" shell=shell_2 python=python_2 javascript=javascript_2 java=java_2 rust=rust_2 %} #### Output @@ -90,9 +174,37 @@ Usage: `ACL DELUSER ` #### Example -``` -> ACL DELUSER john -``` +{% capture shell_3 %} +ACL DELUSER john +{% endcapture %} + +{% capture python_3 %} +from falkordb import FalkorDB +client = FalkorDB() +result = client.execute_command('ACL', 'DELUSER', 'john') +print(result) +{% endcapture %} + +{% capture javascript_3 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const result = await client.sendCommand(['ACL', 'DELUSER', 'john']); +console.log(result); +{% endcapture %} + +{% capture java_3 %} +FalkorDB client = new FalkorDB(); +Object result = client.sendCommand("ACL", "DELUSER", "john"); +System.out.println(result); +{% endcapture %} + +{% capture rust_3 %} +let client = FalkorDB::connect_default(); +let result = client.execute_command(&["ACL", "DELUSER", "john"])?; +println!("{:?}", result); +{% endcapture %} + +{% include code_tabs.html id="deluser_tabs" shell=shell_3 python=python_3 javascript=javascript_3 java=java_3 rust=rust_3 %} ### ACL LIST @@ -102,9 +214,37 @@ Usage: `ACL LIST` #### Example -``` -> ACL LIST -``` +{% capture shell_4 %} +ACL LIST +{% endcapture %} + +{% capture python_4 %} +from falkordb import FalkorDB +client = FalkorDB() +users = client.execute_command('ACL', 'LIST') +print(users) +{% endcapture %} + +{% capture javascript_4 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const users = await client.sendCommand(['ACL', 'LIST']); +console.log(users); +{% endcapture %} + +{% capture java_4 %} +FalkorDB client = new FalkorDB(); +Object users = client.sendCommand("ACL", "LIST"); +System.out.println(users); +{% endcapture %} + +{% capture rust_4 %} +let client = FalkorDB::connect_default(); +let users = client.execute_command(&["ACL", "LIST"])?; +println!("{:?}", users); +{% endcapture %} + +{% include code_tabs.html id="list_tabs" shell=shell_4 python=python_4 javascript=javascript_4 java=java_4 rust=rust_4 %} #### Output @@ -124,9 +264,37 @@ Usage: `ACL LOG [count]` #### Example -``` -> ACL LOG 10 -``` +{% capture shell_5 %} +ACL LOG 10 +{% endcapture %} + +{% capture python_5 %} +from falkordb import FalkorDB +client = FalkorDB() +log_entries = client.execute_command('ACL', 'LOG', '10') +print(log_entries) +{% endcapture %} + +{% capture javascript_5 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const logEntries = await client.sendCommand(['ACL', 'LOG', '10']); +console.log(logEntries); +{% endcapture %} + +{% capture java_5 %} +FalkorDB client = new FalkorDB(); +Object logEntries = client.sendCommand("ACL", "LOG", "10"); +System.out.println(logEntries); +{% endcapture %} + +{% capture rust_5 %} +let client = FalkorDB::connect_default(); +let log_entries = client.execute_command(&["ACL", "LOG", "10"])?; +println!("{:?}", log_entries); +{% endcapture %} + +{% include code_tabs.html id="log_tabs" shell=shell_5 python=python_5 javascript=javascript_5 java=java_5 rust=rust_5 %} ## Notes diff --git a/commands/graph.constraint-drop.md b/commands/graph.constraint-drop.md index ffd7319..acb4296 100644 --- a/commands/graph.constraint-drop.md +++ b/commands/graph.constraint-drop.md @@ -8,15 +8,7 @@ nav_order: 8 # GRAPH.CONSTRAINT DROP ---- -syntax: | - GRAPH.CONSTRAINT DROP key - MANDATORY|UNIQUE - NODE label | RELATIONSHIP reltype - PROPERTIES propCount prop [prop...] ---- - -Deleted a graph constraint. +Deletes a graph constraint. [Examples](#examples) diff --git a/commands/graph.explain.md b/commands/graph.explain.md index 3ef9d4a..72aea4a 100644 --- a/commands/graph.explain.md +++ b/commands/graph.explain.md @@ -54,3 +54,134 @@ println!("{}", result); {% endcapture %} {% include code_tabs.html id="explain_tabs" shell=shell_0 python=python_0 javascript=javascript_0 java=java_0 rust=rust_0 %} + +## Sample Output + +When you run `GRAPH.EXPLAIN`, you get a text representation of the execution plan that shows how FalkorDB will process your query. Here's an example: + +``` +Results + Project + Filter + Node By Label Scan | (p:President) +``` + +### Interpreting Execution Plans + +The execution plan is displayed as a tree structure, where operations are indented to show their hierarchy. The query is executed from bottom to top (innermost to outermost operations). + +#### Common Operations + +| Operation | Description | When It's Used | +|-----------|-------------|----------------| +| `Node By Label Scan` | Scans all nodes with a specific label | When querying nodes by label (e.g., `MATCH (n:User)`) | +| `All Node Scan` | Scans all nodes in the graph | When no label filter is specified (e.g., `MATCH (n)`) | +| `Filter` | Applies WHERE clause conditions | When filtering results with WHERE | +| `Conditional Traverse` | Follows relationships matching criteria | When traversing edges with conditions | +| `Expand Into` | Expands from one node to another specific node | When both endpoints are bound | +| `Project` | Selects specific properties/expressions | Corresponds to RETURN clause | +| `Aggregate` | Performs aggregation (COUNT, SUM, etc.) | When using aggregation functions | +| `Sort` | Orders results | When using ORDER BY | +| `Skip` | Skips the first N results | When using SKIP | +| `Limit` | Limits number of results | When using LIMIT | +| `Create Node` | Creates new nodes | When using CREATE with nodes | +| `Create Edge` | Creates new relationships | When using CREATE with relationships | + +### Example: Complex Query Execution Plan + +{% capture shell_1 %} +GRAPH.EXPLAIN social "MATCH (u:User)-[:FOLLOWS]->(f:User) WHERE u.age > 25 AND f.verified = true RETURN u.name, f.name ORDER BY u.age LIMIT 10" +{% endcapture %} + +{% capture python_1 %} +query = """ +MATCH (u:User)-[:FOLLOWS]->(f:User) +WHERE u.age > 25 AND f.verified = true +RETURN u.name, f.name +ORDER BY u.age +LIMIT 10 +""" +plan = graph.explain(query) +print(plan) +{% endcapture %} + +{% capture javascript_1 %} +const query = ` + MATCH (u:User)-[:FOLLOWS]->(f:User) + WHERE u.age > 25 AND f.verified = true + RETURN u.name, f.name + ORDER BY u.age + LIMIT 10 +`; +const plan = await graph.explain(query); +console.log(plan); +{% endcapture %} + +{% capture java_1 %} +String query = "MATCH (u:User)-[:FOLLOWS]->(f:User) " + + "WHERE u.age > 25 AND f.verified = true " + + "RETURN u.name, f.name " + + "ORDER BY u.age LIMIT 10"; +String plan = graph.explain(query); +System.out.println(plan); +{% endcapture %} + +{% capture rust_1 %} +let query = r#" + MATCH (u:User)-[:FOLLOWS]->(f:User) + WHERE u.age > 25 AND f.verified = true + RETURN u.name, f.name + ORDER BY u.age + LIMIT 10 +"#; +let plan = graph.explain(query)?; +println!("{}", plan); +{% endcapture %} + +{% include code_tabs.html id="complex_explain_tabs" shell=shell_1 python=python_1 javascript=javascript_1 java=java_1 rust=rust_1 %} + +**Sample Output:** +``` +Results + Limit + Sort + Project + Filter + Conditional Traverse | (u:User)-[:FOLLOWS]->(f:User) + Filter + Node By Label Scan | (u:User) +``` + +**Reading the plan (bottom to top):** +1. `Node By Label Scan | (u:User)` - Find all User nodes and bind to 'u' +2. `Filter` - Apply condition `u.age > 25` +3. `Conditional Traverse | (u:User)-[:FOLLOWS]->(f:User)` - Follow FOLLOWS relationships to other User nodes +4. `Filter` - Apply condition `f.verified = true` +5. `Project` - Extract `u.name` and `f.name` +6. `Sort` - Order by `u.age` +7. `Limit` - Take only first 10 results + +### Example: Indexed Query + +When an index exists on a property used in a WHERE clause, the execution plan will show index usage: + +``` +Results + Project + Conditional Traverse | (u:User)-[:FOLLOWS]->(f:User) + Node By Index Scan | (u:User) +``` + +The `Node By Index Scan` operation indicates that an index is being used, which is typically much faster than a full label scan. + +## Use Cases + +- **Query Optimization**: Identify operations that might be slow (e.g., `All Node Scan` on large graphs) +- **Index Verification**: Confirm that indexes are being used in your queries +- **Understanding Performance**: See how FalkorDB interprets your Cypher queries +- **Debugging**: Validate that your query logic matches your intentions + +## See Also + +- [`GRAPH.PROFILE`](/commands/graph.profile) - Similar to EXPLAIN but actually runs the query and provides detailed statistics +- [Cypher documentation](/cypher) - Learn about query optimization and best practices diff --git a/commands/graph.info.md b/commands/graph.info.md index 3c96449..b6f1c33 100644 --- a/commands/graph.info.md +++ b/commands/graph.info.md @@ -16,22 +16,166 @@ Returns information and statistics about currently running and waiting queries. GRAPH.INFO [RunningQueries | WaitingQueries] ``` +## Arguments + +| Argument | Type | Required | Description | +|----------|------|----------|-------------| +| `RunningQueries` | keyword | No | Return only currently executing queries | +| `WaitingQueries` | keyword | No | Return only queries waiting in the queue | + If no argument is provided, both running and waiting queries are returned. +## Returns + +Returns an array containing two sections: + +1. **Running queries** - List of queries currently being executed with details: + - Query text + - Graph name + - Execution time (milliseconds) + - Client information +2. **Waiting queries** - List of queries in the queue waiting to be executed + +Each query entry includes metadata that helps identify long-running operations and monitor query performance. + ## Examples +### Get All Query Information + +{% capture shell_0 %} +GRAPH.INFO +{% endcapture %} + +{% capture python_0 %} +from falkordb import FalkorDB +client = FalkorDB() +info = client.call_procedure('GRAPH.INFO') +print(info) +{% endcapture %} + +{% capture javascript_0 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const info = await client.info(); +console.log(info); +{% endcapture %} + +{% capture java_0 %} +FalkorDB client = new FalkorDB(); +List> info = client.info(); +System.out.println(info); +{% endcapture %} + +{% capture rust_0 %} +let client = FalkorDB::connect_default(); +let info = client.info()?; +println!("{:?}", info); +{% endcapture %} + +{% include code_tabs.html id="info_all_tabs" shell=shell_0 python=python_0 javascript=javascript_0 java=java_0 rust=rust_0 %} + +**Sample Output (when no queries are running):** ```sh -127.0.0.1:6379> GRAPH.INFO 1) "# Running queries" 2) (empty array) 3) "# Waiting queries" 4) (empty array) +``` + +### Get Running Queries Only + +{% capture shell_1 %} +GRAPH.INFO RunningQueries +{% endcapture %} + +{% capture python_1 %} +from falkordb import FalkorDB +client = FalkorDB() +running = client.call_procedure('GRAPH.INFO', 'RunningQueries') +print(running) +{% endcapture %} + +{% capture javascript_1 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const running = await client.info('RunningQueries'); +console.log(running); +{% endcapture %} + +{% capture java_1 %} +FalkorDB client = new FalkorDB(); +List> running = client.info("RunningQueries"); +System.out.println(running); +{% endcapture %} -127.0.0.1:6379> GRAPH.INFO RunningQueries +{% capture rust_1 %} +let client = FalkorDB::connect_default(); +let running = client.info_running_queries()?; +println!("{:?}", running); +{% endcapture %} + +{% include code_tabs.html id="running_tabs" shell=shell_1 python=python_1 javascript=javascript_1 java=java_1 rust=rust_1 %} + +**Sample Output (with active query):** +```sh 1) "# Running queries" -2) (empty array) +2) 1) 1) "graph: my_graph" + 2) "query: MATCH (n)-[*]->() RETURN n" + 3) "elapsed time (ms): 1250" + 4) "client: 127.0.0.1:52341" +``` + +### Get Waiting Queries Only + +{% capture shell_2 %} +GRAPH.INFO WaitingQueries +{% endcapture %} + +{% capture python_2 %} +from falkordb import FalkorDB +client = FalkorDB() +waiting = client.call_procedure('GRAPH.INFO', 'WaitingQueries') +print(waiting) +{% endcapture %} + +{% capture javascript_2 %} +import { FalkorDB } from 'falkordb'; +const client = await FalkorDB.connect(); +const waiting = await client.info('WaitingQueries'); +console.log(waiting); +{% endcapture %} -127.0.0.1:6379> GRAPH.INFO WaitingQueries +{% capture java_2 %} +FalkorDB client = new FalkorDB(); +List> waiting = client.info("WaitingQueries"); +System.out.println(waiting); +{% endcapture %} + +{% capture rust_2 %} +let client = FalkorDB::connect_default(); +let waiting = client.info_waiting_queries()?; +println!("{:?}", waiting); +{% endcapture %} + +{% include code_tabs.html id="waiting_tabs" shell=shell_2 python=python_2 javascript=javascript_2 java=java_2 rust=rust_2 %} + +**Sample Output (with queued queries):** +```sh 1) "# Waiting queries" -2) (empty array) +2) 1) 1) "graph: analytics" + 2) "query: MATCH (n:User) WHERE n.age > 25 RETURN count(n)" + 3) "wait time (ms): 45" ``` + +## Use Cases + +- **Performance Monitoring**: Identify slow queries that may need optimization +- **Debugging**: See what queries are currently executing when investigating issues +- **Capacity Planning**: Monitor query queue depth to understand server load +- **Query Optimization**: Track execution times to identify bottlenecks + +## Notes + +- The `CMD_INFO` configuration parameter controls whether this command is enabled +- Disabling `GRAPH.INFO` may improve performance and reduce memory usage +- See [`MAX_INFO_QUERIES`](/getting-started/configuration#max_info_queries) to control query history size diff --git a/commands/graph.query.md b/commands/graph.query.md index 95b7546..4179468 100644 --- a/commands/graph.query.md +++ b/commands/graph.query.md @@ -10,9 +10,34 @@ parent: "Commands" Executes the given query against a specified graph. -Arguments: `Graph name, Query, Timeout [optional]` +## Syntax -Returns: [Result set](/design/result-structure) +``` +GRAPH.QUERY graph_name "query" [TIMEOUT timeout_value] +``` + +## Arguments + +| Argument | Type | Required | Description | +|----------|------|----------|-------------| +| `graph_name` | string | Yes | The name of the graph to query | +| `query` | string | Yes | A Cypher query to execute against the graph | +| `TIMEOUT` | integer | No | Query timeout in milliseconds. Overrides the default timeout. Cannot exceed `TIMEOUT_MAX` configuration | + +## Returns + +Returns a [result set](/design/result-structure) containing: + +1. **Header** - Column names corresponding to the RETURN clause +2. **Data rows** - Query results as nested arrays containing: + - Scalar values (integers, strings, booleans, floats, null) + - Graph entities (nodes with IDs, labels, and properties) + - Relationships (edges with IDs, types, source/destination nodes, and properties) + - Collections (arrays and paths) +3. **Metadata** - Query execution statistics including: + - Query execution time + - Number of entities created, deleted, or modified + - Cache status ### Queries and Parameterized Queries @@ -97,6 +122,216 @@ println!("{:?}", result); {% include code_tabs.html id="tabs_1" shell=shell_1 python=python_1 javascript=javascript_1 java=java_1 rust=rust_1 %} -### Query language +## Query Timeout + +Queries can be given a timeout to prevent long-running operations from blocking server resources. The timeout is specified in milliseconds using the optional `TIMEOUT` parameter. + +### Timeout Configuration + +- **Per-Query Timeout**: Use the `TIMEOUT` parameter to set a timeout for a specific query +- **Default Timeout**: Configured globally using [`TIMEOUT_DEFAULT`](/getting-started/configuration#timeout_default) +- **Maximum Timeout**: Limited by [`TIMEOUT_MAX`](/getting-started/configuration#timeout_max) configuration + +### Example + +{% capture shell_2 %} +GRAPH.QUERY wikipedia "MATCH p=()-[*]->() RETURN p" TIMEOUT 500 +{% endcapture %} + +{% capture python_2 %} +# Timeout in milliseconds +graph.query("MATCH p=()-[*]->() RETURN p", timeout=500) +{% endcapture %} + +{% capture javascript_2 %} +// Timeout in milliseconds +const result = await graph.query( + "MATCH p=()-[*]->() RETURN p", + { timeout: 500 } +); +{% endcapture %} + +{% capture java_2 %} +// Timeout in milliseconds +ResultSet result = graph.query( + "MATCH p=()-[*]->() RETURN p", + 500 // timeout +); +{% endcapture %} + +{% capture rust_2 %} +// Timeout in milliseconds +let result = graph.query(r#"MATCH p=()-[*]->() RETURN p"#) + .timeout(500) + .execute() + .await?; +{% endcapture %} + +{% include code_tabs.html id="timeout_tabs" shell=shell_2 python=python_2 javascript=javascript_2 java=java_2 rust=rust_2 %} + +When a query exceeds its timeout, it is aborted and returns an error: `(error) Query timed out`. For write queries, any changes to the graph are rolled back (which may take additional time). + +## Write Operations + +`GRAPH.QUERY` supports both read and write operations. Write operations modify the graph structure and include: + +- **CREATE**: Create new nodes and relationships +- **SET**: Update properties on existing entities +- **DELETE**: Remove nodes and relationships +- **MERGE**: Create entities if they don't exist, or match existing ones +- **REMOVE**: Remove properties or labels from entities + +### Write Query Example + +{% capture shell_3 %} +GRAPH.QUERY social "CREATE (u:User {name: 'Alice', age: 30})-[:FRIENDS_WITH]->(v:User {name: 'Bob', age: 28})" +{% endcapture %} + +{% capture python_3 %} +result = graph.query( + "CREATE (u:User {name: $name, age: $age})-[:FRIENDS_WITH]->(v:User {name: $friend, age: $friend_age})", + {'name': 'Alice', 'age': 30, 'friend': 'Bob', 'friend_age': 28} +) +# Check metadata for created entities +print(result.nodes_created, result.relationships_created) +{% endcapture %} + +{% capture javascript_3 %} +const result = await graph.query( + "CREATE (u:User {name: $name, age: $age})-[:FRIENDS_WITH]->(v:User {name: $friend, age: $friend_age})", + { params: { name: 'Alice', age: 30, friend: 'Bob', friend_age: 28 } } +); +console.log(`Created ${result.getStatistics().nodesCreated} nodes`); +{% endcapture %} + +{% capture java_3 %} +Map params = new HashMap<>(); +params.put("name", "Alice"); +params.put("age", 30); +params.put("friend", "Bob"); +params.put("friend_age", 28); +ResultSet result = graph.query( + "CREATE (u:User {name: $name, age: $age})-[:FRIENDS_WITH]->(v:User {name: $friend, age: $friend_age})", + params +); +System.out.println("Nodes created: " + result.getStatistics().nodesCreated()); +{% endcapture %} + +{% capture rust_3 %} +let params = std::collections::HashMap::from([ + ("name", "Alice"), + ("age", "30"), + ("friend", "Bob"), + ("friend_age", "28") +]); +let result = graph.query_with_params( + r#"CREATE (u:User {name: $name, age: $age})-[:FRIENDS_WITH]->(v:User {name: $friend, age: $friend_age})"#, + ¶ms +).execute().await?; +println!("Nodes created: {}", result.nodes_created); +{% endcapture %} + +{% include code_tabs.html id="write_tabs" shell=shell_3 python=python_3 javascript=javascript_3 java=java_3 rust=rust_3 %} + +Write operations return metadata indicating the number of entities created, deleted, or modified. Unlike read-only queries (which can use [`GRAPH.RO_QUERY`](/commands/graph.ro-query)), write queries can timeout and will rollback changes when they do. + +## Error Handling + +Common errors when executing queries: + +| Error | Description | Resolution | +|-------|-------------|------------| +| `Query timed out` | Query execution exceeded the timeout limit | Increase timeout, optimize query, or check for infinite loops | +| `Max pending queries exceeded` | Too many concurrent queries | Wait and retry, or increase `MAX_QUEUED_QUERIES` configuration | +| `Query's mem consumption exceeded capacity` | Query used too much memory | Optimize query or increase `QUERY_MEM_CAPACITY` configuration | +| `Syntax error` | Invalid Cypher syntax | Check query syntax against [Cypher documentation](/cypher) | +| `Unknown graph` | Graph does not exist | Create the graph first or check graph name | + +### Example Error Handling + +{% capture python_4 %} +from falkordb import FalkorDB +from redis.exceptions import ResponseError + +client = FalkorDB() +graph = client.select_graph('my_graph') + +try: + result = graph.query("MATCH (n) RETURN n", timeout=1000) +except ResponseError as e: + if "timed out" in str(e): + print("Query timed out, try optimizing or increasing timeout") + elif "Syntax error" in str(e): + print("Invalid query syntax") + else: + print(f"Query error: {e}") +{% endcapture %} + +{% capture javascript_4 %} +import { FalkorDB } from 'falkordb'; + +const client = await FalkorDB.connect(); +const graph = client.selectGraph('my_graph'); + +try { + const result = await graph.query("MATCH (n) RETURN n", { timeout: 1000 }); +} catch (error) { + if (error.message.includes('timed out')) { + console.log('Query timed out, try optimizing or increasing timeout'); + } else if (error.message.includes('Syntax error')) { + console.log('Invalid query syntax'); + } else { + console.error('Query error:', error.message); + } +} +{% endcapture %} + +{% capture java_4 %} +import com.falkordb.FalkorDB; +import com.falkordb.Graph; +import com.falkordb.ResultSet; +import redis.clients.jedis.exceptions.JedisDataException; + +FalkorDB client = new FalkorDB(); +Graph graph = client.selectGraph("my_graph"); + +try { + ResultSet result = graph.query("MATCH (n) RETURN n", 1000); +} catch (JedisDataException e) { + String message = e.getMessage(); + if (message.contains("timed out")) { + System.out.println("Query timed out, try optimizing or increasing timeout"); + } else if (message.contains("Syntax error")) { + System.out.println("Invalid query syntax"); + } else { + System.err.println("Query error: " + message); + } +} +{% endcapture %} + +{% capture rust_4 %} +use falkordb::{FalkorDB, FalkorDBError}; + +let client = FalkorDB::connect_default(); +let graph = client.select_graph("my_graph"); + +match graph.query(r#"MATCH (n) RETURN n"#).timeout(1000).execute().await { + Ok(result) => println!("Query succeeded"), + Err(e) => { + let error_msg = e.to_string(); + if error_msg.contains("timed out") { + println!("Query timed out, try optimizing or increasing timeout"); + } else if error_msg.contains("Syntax error") { + println!("Invalid query syntax"); + } else { + eprintln!("Query error: {}", error_msg); + } + } +} +{% endcapture %} + +{% include code_tabs.html id="error_tabs" python=python_4 javascript=javascript_4 java=java_4 rust=rust_4 %} + +## Query Language The syntax is based on [Cypher](http://www.opencypher.org/). [Most](/cypher/cypher-support) of the language is supported. See [Cypher documentation](/cypher). \ No newline at end of file diff --git a/udfs/flex/bitwise/index.md b/udfs/flex/bitwise/index.md index a9ec199..6783077 100644 --- a/udfs/flex/bitwise/index.md +++ b/udfs/flex/bitwise/index.md @@ -10,4 +10,23 @@ nav_order: 10 # Bitwise Functions -FLEX bitwise utilities. \ No newline at end of file +FLEX bitwise utilities provide operations for manipulating integer values at the bit level. These functions are useful for working with flags, permissions, masks, and other low-level data operations. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [bitwise.and](./and.md) | Performs bitwise AND operation on two integers | +| [bitwise.or](./or.md) | Performs bitwise OR operation on two integers | +| [bitwise.xor](./xor.md) | Performs bitwise XOR (exclusive OR) operation on two integers | +| [bitwise.not](./not.md) | Performs bitwise NOT (complement) operation on an integer | +| [bitwise.shiftLeft](./shiftLeft.md) | Shifts bits to the left by a specified number of positions | +| [bitwise.shiftRight](./shiftRight.md) | Shifts bits to the right by a specified number of positions | + +## Common Use Cases + +- **Permission Systems**: Check and manipulate user permissions using bit flags +- **Data Compression**: Encode multiple boolean values in a single integer +- **Network Operations**: Work with IP addresses, subnet masks, and network protocols +- **Hardware Interfacing**: Control and read hardware registers and flags +- **Cryptography**: Implement encryption algorithms requiring bit manipulation \ No newline at end of file diff --git a/udfs/flex/collections/index.md b/udfs/flex/collections/index.md index 6318a67..ca78ff6 100644 --- a/udfs/flex/collections/index.md +++ b/udfs/flex/collections/index.md @@ -10,4 +10,21 @@ nav_order: 20 # Collection Functions -FLEX collections utilities. \ No newline at end of file +FLEX collections utilities provide functions for working with lists and arrays. These functions enable advanced list manipulation, set operations, and data transformation operations. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [collections.frequencies](./frequencies.md) | Count occurrences of each element in a collection | +| [collections.intersection](./intersection.md) | Find common elements between two collections | +| [collections.shuffle](./shuffle.md) | Randomly shuffle elements in a collection | +| [collections.union](./union.md) | Combine two collections, removing duplicates | +| [collections.zip](./zip.md) | Combine two collections into pairs | + +## Common Use Cases + +- **Set Operations**: Perform union, intersection, and other set-like operations on lists +- **Data Analysis**: Count element frequencies and find patterns in data +- **Randomization**: Shuffle data for sampling or randomization purposes +- **Data Transformation**: Combine and restructure collections for processing \ No newline at end of file diff --git a/udfs/flex/date/index.md b/udfs/flex/date/index.md index 4ed7bdc..e9a0bab 100644 --- a/udfs/flex/date/index.md +++ b/udfs/flex/date/index.md @@ -10,4 +10,20 @@ nav_order: 30 # Date Functions -FLEX date utilities. \ No newline at end of file +FLEX date utilities provide functions for working with dates, times, and timestamps. These functions enable date formatting, parsing, timezone conversion, and date manipulation operations. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [date.format](./format.md) | Format a date/timestamp into a string representation | +| [date.parse](./parse.md) | Parse a date string into a timestamp | +| [date.toTimeZone](./toTimeZone.md) | Convert a timestamp to a different timezone | +| [date.truncate](./truncate.md) | Truncate a timestamp to a specific unit (day, hour, etc.) | + +## Common Use Cases + +- **Date Formatting**: Display dates in human-readable formats +- **Date Parsing**: Convert date strings from various formats into timestamps +- **Timezone Handling**: Work with dates across different timezones +- **Time Bucketing**: Group events by time periods (hourly, daily, etc.) \ No newline at end of file diff --git a/udfs/flex/json/index.md b/udfs/flex/json/index.md index 14a11c9..55d8f08 100644 --- a/udfs/flex/json/index.md +++ b/udfs/flex/json/index.md @@ -10,4 +10,19 @@ nav_order: 40 # JSON Functions -FLEX json utilities. \ No newline at end of file +FLEX json utilities provide functions for converting between JSON strings and native data structures. These functions enable JSON serialization and deserialization for working with JSON data in Cypher queries. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [json.fromJsonList](./fromJsonList.md) | Parse a JSON array string into a list | +| [json.fromJsonMap](./fromJsonMap.md) | Parse a JSON object string into a map | +| [json.toJson](./toJson.md) | Convert a value (list, map, etc.) to a JSON string | + +## Common Use Cases + +- **API Integration**: Parse JSON responses from external APIs +- **Data Import/Export**: Convert between JSON and native graph structures +- **Configuration Storage**: Store and retrieve JSON configuration data +- **Data Serialization**: Convert complex data structures to JSON for storage or transmission \ No newline at end of file diff --git a/udfs/flex/map/index.md b/udfs/flex/map/index.md index d5c17c0..cbf6fb5 100644 --- a/udfs/flex/map/index.md +++ b/udfs/flex/map/index.md @@ -10,4 +10,21 @@ nav_order: 50 # Map Functions -FLEX map utilities. \ No newline at end of file +FLEX map utilities provide functions for working with key-value maps (objects). These functions enable map manipulation, merging, filtering, and transformation operations. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [map.fromPairs](./fromPairs.md) | Create a map from a list of key-value pairs | +| [map.merge](./merge.md) | Merge multiple maps into a single map | +| [map.removeKey](./removeKey.md) | Remove a single key from a map | +| [map.removeKeys](./removeKeys.md) | Remove multiple keys from a map | +| [map.submap](./submap.md) | Extract a subset of a map by selecting specific keys | + +## Common Use Cases + +- **Data Transformation**: Restructure and transform map data +- **Property Management**: Add, remove, or update node/relationship properties +- **Configuration Merging**: Combine default and custom configuration maps +- **Data Filtering**: Extract only needed fields from complex data structures \ No newline at end of file diff --git a/udfs/flex/similarity/index.md b/udfs/flex/similarity/index.md index ddd9220..8b1ec21 100644 --- a/udfs/flex/similarity/index.md +++ b/udfs/flex/similarity/index.md @@ -10,4 +10,17 @@ nav_order: 60 # Similarity Functions -FLEX similarity utilities. \ No newline at end of file +FLEX similarity utilities provide functions for measuring similarity between data structures. These functions are useful for comparing sets, finding duplicates, and implementing recommendation systems. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [similarity.jaccard](./jaccard.md) | Calculate Jaccard similarity coefficient between two sets | + +## Common Use Cases + +- **Recommendation Systems**: Find similar items based on shared attributes +- **Duplicate Detection**: Identify similar or duplicate records +- **Set Comparison**: Measure how similar two sets of items are +- **Content Similarity**: Compare collections of tags, categories, or features \ No newline at end of file diff --git a/udfs/flex/text/index.md b/udfs/flex/text/index.md index 0b8f8ba..1c8dd6f 100644 --- a/udfs/flex/text/index.md +++ b/udfs/flex/text/index.md @@ -10,4 +10,34 @@ nav_order: 70 # Text Functions -FLEX text utilities. \ No newline at end of file +FLEX text utilities provide comprehensive functions for string manipulation, formatting, and text analysis. These functions enable case conversion, formatting, searching, similarity measurement, and string transformation operations. + +## Available Functions + +| Function | Description | +|----------|-------------| +| [text.camelCase](./camelCase.md) | Convert string to camelCase format | +| [text.capitalize](./capitalize.md) | Capitalize the first character of a string | +| [text.decapitalize](./decapitalize.md) | Convert the first character to lowercase | +| [text.format](./format.md) | Format a string with placeholders and arguments | +| [text.indexOf](./indexOf.md) | Find the first occurrence of a substring | +| [text.indexesOf](./indexesOf.md) | Find all occurrences of a substring | +| [text.jaroWinkler](./jaroWinkler.md) | Calculate Jaro-Winkler string similarity distance | +| [text.join](./join.md) | Join a list of strings with a separator | +| [text.levenshtein](./levenshtein.md) | Calculate Levenshtein edit distance between strings | +| [text.lpad](./lpad.md) | Pad string on the left to a specified length | +| [text.regexGroups](./regexGroups.md) | Extract regex capture groups from a string | +| [text.repeat](./repeat.md) | Repeat a string a specified number of times | +| [text.replace](./replace.md) | Replace occurrences of a substring with another string | +| [text.rpad](./rpad.md) | Pad string on the right to a specified length | +| [text.snakeCase](./snakeCase.md) | Convert string to snake_case format | +| [text.swapCase](./swapCase.md) | Swap the case of all characters in a string | +| [text.upperCamelCase](./upperCamelCase.md) | Convert string to UpperCamelCase (PascalCase) format | + +## Common Use Cases + +- **Text Formatting**: Format strings for display, normalize case conventions +- **String Searching**: Find and extract substrings and patterns +- **Fuzzy Matching**: Compare strings and find similar text using distance metrics +- **Data Cleaning**: Normalize and standardize text data +- **Text Transformation**: Convert between naming conventions and formats \ No newline at end of file