From c84755db3ff8038e533dbb2e98e5b6d50cb5c0ca Mon Sep 17 00:00:00 2001 From: imilinovic Date: Mon, 18 May 2026 14:55:47 +0200 Subject: [PATCH] Document cross_database module (deprecates migrate in 3.11) Add the cross_database reference page covering all procedures (bolt, neo4j, mysql, postgresql, sql_server, oracle_db, s3, arrow_flight, duckdb, servicenow), the Bolt type conversion rules (including the lossy 30-days-per-month Duration flattening), the same-parameters guard, and the migrate.* alias table. Reduce the migrate page to a redirect stub pointing at cross_database; the migrate.* names continue to work via Memgraph's callable-mapping aliases, but the canonical reference now lives at cross_database. --- .../available-algorithms/_meta.ts | 1 + .../available-algorithms/cross_database.mdx | 462 ++++++++++++++ .../available-algorithms/migrate.mdx | 567 +----------------- 3 files changed, 472 insertions(+), 558 deletions(-) create mode 100644 pages/advanced-algorithms/available-algorithms/cross_database.mdx diff --git a/pages/advanced-algorithms/available-algorithms/_meta.ts b/pages/advanced-algorithms/available-algorithms/_meta.ts index 6795c2595..885416252 100644 --- a/pages/advanced-algorithms/available-algorithms/_meta.ts +++ b/pages/advanced-algorithms/available-algorithms/_meta.ts @@ -13,6 +13,7 @@ export default { "convert_c": "convert_c", "do": "do", "create": "create", + "cross_database": "cross_database", "cugraph": "cugraph", "cycles": "cycles", "date": "date", diff --git a/pages/advanced-algorithms/available-algorithms/cross_database.mdx b/pages/advanced-algorithms/available-algorithms/cross_database.mdx new file mode 100644 index 000000000..dd60e8a42 --- /dev/null +++ b/pages/advanced-algorithms/available-algorithms/cross_database.mdx @@ -0,0 +1,462 @@ +--- +title: cross_database +description: Query other databases (Memgraph, Neo4j, PostgreSQL, MySQL, Oracle, SQL Server, S3, Arrow Flight, DuckDB, ServiceNow) directly from Memgraph and stream their rows into your graph. +--- + +import { Cards } from 'nextra/components' +import GitHub from '/components/icons/GitHub' +import { Callout } from 'nextra/components'; + +# cross_database + +The `cross_database` module lets you reach into another database from a running Cypher query and stream +its rows into Memgraph. Use it to migrate data, build hybrid OLTP/graph pipelines, or join graph data +with rows fetched on-demand from a relational/Bolt/object-store source. + + +**The `migrate` module is deprecated as of Memgraph 3.11** and has been replaced by `cross_database`. +Existing `migrate.*` calls keep working via the [aliases](#backwards-compatibility-with-migrate) shipped +with Memgraph, but new code should call `cross_database.*` directly. The previous `migrate.memgraph()` +procedure has been replaced by the more general [`cross_database.bolt()`](#bolt). + + + + } + title="Source code" + href="https://github.com/memgraph/memgraph/blob/master/mage/python/cross_database.py" + /> + + +| Trait | Value | +| ------------------- | ---------- | +| **Module type** | util | +| **Implementation** | Python | +| **Parallelism** | sequential | + + +When running multiple cross-database calls against the same source, avoid repeating the `config` map in every call. +Use [server-side parameters](/database-management/server-side-parameters) to store the connection config once +and reference it as `$config` across all your queries: + +```cypher +SET GLOBAL PARAMETER pg_config = {user: 'memgraph', password: 'password', host: 'localhost', database: 'demo_db'}; + +CALL cross_database.postgresql('users', $pg_config) YIELD row CREATE (u:User {id: row.id}); +CALL cross_database.postgresql('orders', $pg_config) YIELD row CREATE (o:Order {id: row.id}); +``` + + +## Backwards compatibility with `migrate` + +Every procedure listed below has a `migrate.*` alias preserved from earlier versions, so existing queries +keep working unchanged. The aliases are wired up through Memgraph's callable-mapping mechanism +(`/etc/memgraph/apoc_compatibility_mappings.json`, enabled by default), so no configuration is required. + +| Pre-3.11 name | New name | +| -------------------------- | --------------------------------- | +| `migrate.memgraph` | `cross_database.bolt` | +| `migrate.neo4j` | `cross_database.neo4j` | +| `migrate.mysql` | `cross_database.mysql` | +| `migrate.postgresql` | `cross_database.postgresql` | +| `migrate.sql_server` | `cross_database.sql_server` | +| `migrate.oracle_db` | `cross_database.oracle_db` | +| `migrate.s3` | `cross_database.s3` | +| `migrate.arrow_flight` | `cross_database.arrow_flight` | +| `migrate.duckdb` | `cross_database.duckdb` | +| `migrate.servicenow` | `cross_database.servicenow` | + +If you mix old and new names within the same transaction, treat them as the same procedure — calling +`migrate.postgresql` and `cross_database.postgresql` with identical arguments will trigger the +[same-parameters guard](#same-parameters-guard). + +You can inspect the active mapping at runtime with: + +```cypher +SHOW QUERY CALLABLE MAPPINGS; +``` + +## Type conversion + +For Bolt-based sources (`bolt`, `neo4j`), primitives (`Boolean`, `Integer`, `Float`, `String`, `Null`), +lists, maps, the calendar-aware temporal types (`Date`, `LocalTime`, `LocalDateTime`, `DateTime`), and +spatial points (`Point2d`, `Point3d`, with their `srid` preserved) pass through cleanly. The cases worth +knowing about: + +| Source type | Result | Notes | +| ---------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Duration` with `months > 0` | flattened | Months are coerced to 30 days each. **This differs from native Neo4j behavior**, where months are preserved and `date + P1M` stays calendar-aware. See the warning below. | +| `Time` (zoned) | *unsupported* | Memgraph has no zoned-time type. Convert to `LocalTime` on the source side, or carry the offset as a separate column. | +| Enum | *unsupported* | Memgraph enums can't cross the Bolt boundary — the call raises an error. | +| Node / Relationship / Path | *unsupported* | Streaming raw graph objects is not supported. Return their `properties()` / `labels()` instead. | + + +The 30-days-per-month flattening means a duration like `P1M` becomes `30 days` on the Memgraph side, and +`P1Y` becomes `360 days`. Native Neo4j keeps months separate from days, so `date + duration('P1M')` stays +calendar-aware there; after crossing the Bolt boundary into Memgraph that calendar information is gone. +If you need exact calendar arithmetic, fetch the months and days components as separate columns and +reconstruct them on the Memgraph side. + + +## Same-parameters guard + +`cross_database` deliberately rejects two concurrent calls with the same `(query, config, params)` inside +a single transaction. Doing so would race on the underlying connection and yield duplicate rows. The error +message is: + +``` +Cross database module with these parameters is already running. +Please wait for it to finish before starting a new one. +``` + +If you intentionally need two reads from the same source in one transaction, vary the query (for example +add a different `LIMIT`, alias, or comment) so the cache key differs. + +--- + +## Procedures + +### `bolt()` + +`cross_database.bolt()` queries any Bolt-compatible database — Memgraph itself, another Memgraph instance, +or Neo4j — and streams the rows back. This replaces the old `migrate.memgraph()` procedure and is the +recommended way to read from any Bolt source. + +{

Input:

} + +- `label_or_rel_or_query: str` ➡ A label name (`(:Label)`), a relationship type (`[:REL_TYPE]`), or a plain + Cypher query. When a label/relationship shorthand is used, `cross_database.bolt()` synthesises the + matching `MATCH … RETURN labels/properties …` query for you. +- `config: mgp.Map` ➡ Connection parameters. Notable keys: `host` (default `localhost`), `port` + (default `7687`), `username`, `password`, `database`, `uri_scheme` (default `bolt`). +- `config_path: str` (optional) ➡ Path to a JSON file containing connection parameters; values in the + file override values in `config`. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ A `Map` of Cypher parameters passed to + the remote query (e.g. `{val: 42}` for a query using `$val`). + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + - When fetching with the `(:Label)` syntax, each row has `labels` and `properties`. + - When fetching with the `[:REL_TYPE]` syntax, each row has `from_labels`, `to_labels`, + `from_properties`, `to_properties`, and `edge_properties`. + - When passing a plain Cypher query, row keys match the columns the remote query returns. + +{

Usage:

} + +#### Retrieve nodes of a certain label and recreate them locally +```cypher +CALL cross_database.bolt('(:Person)', {host: 'localhost', port: 7687}) +YIELD row +WITH row.labels AS labels, row.properties AS props +CREATE (n:labels) SET n += props; +``` + +#### Pass query parameters +```cypher +CALL cross_database.bolt( + 'MATCH (u:User) WHERE u.id = $id RETURN u.name AS name', + {host: 'localhost', port: 7687}, + '', + {id: 42} +) +YIELD row +RETURN row.name AS name; +``` + +#### Connect to Neo4j with explicit credentials +```cypher +CALL cross_database.bolt( + 'MATCH (n) RETURN count(n) AS cnt', + {host: 'neo4j-host', port: 7687, username: 'neo4j', password: 'secret'} +) +YIELD row +RETURN row.cnt AS cnt; +``` + +--- + +### `neo4j()` + +`cross_database.neo4j()` is a thin convenience wrapper around [`bolt()`](#bolt) that defaults the +credentials to Neo4j's stock `neo4j` / `password`. Use it when you only need to override the host/port. + +{

Input:

} + +Same as [`bolt()`](#bolt). If `username` / `password` are missing from `config`, they default to +`neo4j` / `password`. + +{

Output:

} + +Same as [`bolt()`](#bolt). + +{

Usage:

} + +```cypher +CALL cross_database.neo4j('(:Person)', {host: 'neo4j-host', port: 7687}) +YIELD row +WITH row.labels AS labels, row.properties AS props +CREATE (n:labels) SET n += props; +``` + +--- + +### `mysql()` + +Query MySQL and stream rows back. The result table is converted into a stream that can be used to create +graph structures. + +{

Input:

} + +- `table_or_sql: str` ➡ A table name (a single word — automatically expanded to `SELECT * FROM `) + or a full SQL query. +- `config: mgp.Map` ➡ Connection parameters (as in `mysql.connector.connect`). +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ Query parameters. Accepts a `List` for + `%s`-style placeholders or a `Map` for `%(name)s`-style placeholders (both supported by + `mysql.connector`). + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +#### Retrieve and inspect data +```cypher +CALL cross_database.mysql('example_table', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'demo_db'}) +YIELD row +RETURN row +LIMIT 5000; +``` + +#### Create nodes from migrated data +```cypher +CALL cross_database.mysql('SELECT id, name, age FROM users', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'demo_db'}) +YIELD row +CREATE (u:User {id: row.id, name: row.name, age: row.age}); +``` + +--- + +### `postgresql()` + +Query PostgreSQL and stream rows back. + +{

Input:

} + +- `table_or_sql: str` ➡ Table name or SQL query. +- `config: mgp.Map` ➡ Connection parameters (as in `psycopg2.connect`). +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ Query parameters as a `List` + (psycopg2 uses positional `%s` placeholders). Passing a `Map` raises a `TypeError`. + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +#### Retrieve and inspect data +```cypher +CALL cross_database.postgresql('example_table', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'demo_db'}) +YIELD row +RETURN row +LIMIT 5000; +``` + +#### Establish relationships between orders and customers +```cypher +CALL cross_database.postgresql('SELECT order_id, customer_id FROM orders', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'retail_db'}) +YIELD row +MATCH (o:Order {id: row.order_id}), (c:Customer {id: row.customer_id}) +CREATE (c)-[:PLACED]->(o); +``` + +--- + +### `sql_server()` + +Query SQL Server and stream rows back. + +{

Input:

} + +- `table_or_sql: str` ➡ Table name or SQL query. +- `config: mgp.Map` ➡ Connection parameters (as in `pyodbc.connect`). +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ Query parameters as a `List`. + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +```cypher +CALL cross_database.sql_server('SELECT id, name, role FROM employees', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'company_db'}) +YIELD row +CREATE (e:Employee {id: row.id, name: row.name, role: row.role}); +``` + +--- + +### `oracle_db()` + +Query Oracle DB and stream rows back. + +{

Input:

} + +- `table_or_sql: str` ➡ Table name or SQL query. +- `config: mgp.Map` ➡ Connection parameters (as in `oracledb.connect`). +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ Query parameters. Accepts a `List` for + positional placeholders or a `Map` for `:name`-style named placeholders (both supported by `oracledb`). + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +```cypher +CALL cross_database.oracle_db('SELECT id, name FROM companies', {user: 'memgraph', + password: 'password', + host: 'localhost', + database: 'business_db'}) +YIELD row +MERGE (c:Company {id: row.id}) +SET c.name = row.name; +``` + +--- + +### `s3()` + +Read a CSV file directly from AWS S3 and stream its rows into Memgraph. + +{

Input:

} + +- `file_path: str` ➡ S3 path in the form `s3://bucket-name/path/to/file.csv`. +- `config: mgp.Map` ➡ AWS credentials; all keys optional. Missing keys fall back to the corresponding + environment variables: + - `aws_access_key_id` (env: `AWS_ACCESS_KEY_ID`) + - `aws_secret_access_key` (env: `AWS_SECRET_ACCESS_KEY`) + - `region_name` (env: `AWS_REGION`) + - `aws_session_token` (env: `AWS_SESSION_TOKEN`) +- `config_path: str` (optional) ➡ Path to a JSON file with AWS credentials. + +{

Output:

} + +- `row: mgp.Map` ➡ Each CSV row as a `{column_name: value}` map. + +{

Usage:

} + +```cypher +CALL cross_database.s3('s3://my-bucket/employees.csv', {aws_access_key_id: 'your-key', + aws_secret_access_key: 'your-secret', + region_name: 'eu-central-1'}) +YIELD row +CREATE (e:Employee {id: row.id, name: row.name, position: row.position}); +``` + +--- + +### `arrow_flight()` + +Connect to any data source that speaks the [Arrow Flight RPC protocol](https://arrow.apache.org/docs/format/Flight.html) +(for example, [Dremio](https://www.dremio.com/)) and stream rows in. + +{

Input:

} + +- `query: str` ➡ Query against the data source. +- `config: mgp.Map` ➡ Connection parameters (as in `pyarrow.flight.connect`). Notable keys: `host`, + `port`, `username`, `password`. +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +```cypher +CALL cross_database.arrow_flight('SELECT id, name, age FROM users', {username: 'memgraph', + password: 'password', + host: 'localhost', + port: '12345'}) +YIELD row +CREATE (u:User {id: row.id, name: row.name, age: row.age}); +``` + +--- + +### `duckdb()` + +Connect to DuckDB and use it as a proxy to query the [data sources DuckDB +supports](https://duckdb.org/docs/stable/data/data_sources.html). DuckDB is run in-memory with no +persistence — it's only used to proxy to underlying sources. + +{

Input:

} + +- `query: str` ➡ Table name or SQL query. +- `setup_queries: mgp.Nullable[List[str]]` (optional) ➡ Queries executed before `query`, used to attach + or configure the source DuckDB will proxy to (e.g. `INSTALL httpfs; LOAD httpfs;`). + +{

Output:

} + +- `row: mgp.Map` ➡ The result table as a stream of rows. + +{

Usage:

} + +```cypher +CALL cross_database.duckdb( + 'SELECT * FROM read_csv_auto(''s3://my-bucket/users.csv'')', + ['INSTALL httpfs;', 'LOAD httpfs;'] +) +YIELD row +CREATE (u:User {id: row.id, name: row.name}); +``` + +--- + +### `servicenow()` + +Pull data from the [ServiceNow REST API](https://developer.servicenow.com/dev.do#!/reference/api/xanadu/rest/). +The endpoint must return JSON of the form `{"results": [...]}`. + +{

Input:

} + +- `endpoint: str` ➡ The full ServiceNow URL, including any query parameters. +- `config: mgp.Map` ➡ Connection parameters. Notable keys: `username`, `password` (passed through to + `requests.get`). +- `config_path: str` (optional) ➡ Path to a JSON file with connection parameters. +- `params: mgp.Nullable[mgp.Any]` (optional, default `None`) ➡ Additional URL query parameters, + forwarded to `requests.get(endpoint, params=...)`. Unlike the SQL backends, these are HTTP query + string parameters, not SQL placeholders. + +{

Output:

} + +- `row: mgp.Map` ➡ Each element of `results` as a structured dictionary. + +{

Usage:

} + +```cypher +CALL cross_database.servicenow('http://my_endpoint/api/data', {}) +YIELD row +CREATE (e:Employee {id: row.id, name: row.name, position: row.position}); +``` diff --git a/pages/advanced-algorithms/available-algorithms/migrate.mdx b/pages/advanced-algorithms/available-algorithms/migrate.mdx index 884b57e6d..6cf31632f 100644 --- a/pages/advanced-algorithms/available-algorithms/migrate.mdx +++ b/pages/advanced-algorithms/available-algorithms/migrate.mdx @@ -1,568 +1,19 @@ --- title: migrate -description: Discover the migration capabilities of Memgraph for efficient transfer of graph data between instances. Access tutorials and comprehensive documentation for improved experience throughout the migration. +description: The migrate module was renamed to cross_database in Memgraph 3.11. The migrate.* procedure names continue to work as aliases. --- -import { Cards } from 'nextra/components' -import GitHub from '/components/icons/GitHub' -import { Steps } from 'nextra/components' import { Callout } from 'nextra/components'; # migrate -The `migrate` module provides an efficient way to transfer graph data from various relational databases -into Memgraph. This module allows you to retrieve data from various source systems, -transforming tabular data into graph structures. - -With Cypher, you can shape the migrated data dynamically, making it easy to create nodes, -establish relationships, and enrich your graph. Below are examples showing how to retrieve, -filter, and convert relational data into a graph format. - - - } - title="Source code" - href="https://github.com/memgraph/memgraph/blob/master/mage/python/migrate.py" - /> - - -| Trait | Value | -| ------------------- | ---------- | -| **Module type** | util | -| **Implementation** | Python | -| **Parallelism** | sequential | - - -When running multiple migrations against the same source, avoid repeating the `config` map in every call. -Use [server-side parameters](/database-management/server-side-parameters) to store the connection config once -and reference it as `$config` across all your queries: - -```cypher -SET GLOBAL PARAMETER pg_config = {user: 'memgraph', password: 'password', host: 'localhost', database: 'demo_db'}; - -CALL migrate.postgresql('users', $pg_config) YIELD row CREATE (u:User {id: row.id}); -CALL migrate.postgresql('orders', $pg_config) YIELD row CREATE (o:Order {id: row.id}); -``` + +**The `migrate` module was renamed to [`cross_database`](./cross_database) in Memgraph 3.11.** +The `migrate.*` procedure names continue to work via aliases shipped with Memgraph, but new code +should call `cross_database.*` directly. See the [`cross_database`](./cross_database) page for the +full reference, including the new [`bolt()`](./cross_database#bolt) procedure (which supersedes +`migrate.memgraph()`) and the type-conversion rules that apply when reading from Bolt sources. ---- - -## Procedures - -### `arrow_flight()` - -With the `arrow_flight()` procedure, users can access data sources which support the [Arrow Flight RPC protocol](https://arrow.apache.org/docs/format/Flight.html) for transfer -of large data records to achieve high performance. Underlying implementation is using the `pyarrow` Python library to stream rows to -Memgraph. [Dremio](https://www.dremio.com/) is a confirmed data source that works with the `arrow_flight()` procedure. Other sources may also be compatible, but Dremio is based on previous experience. - -{

Input:

} - -- `query: str` ➡ Query used to query the data source. -- `config: mgp.Map` ➡ Connection parameters (as in `pyarrow.flight.connect`). Useful parameters for connecting are `host`, `port`, `username` and `password`. -- `config_path` ➡ Path to a JSON file containing configuration parameters. - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -#### Retrieve and inspect data -```cypher -CALL migrate.arrow_flight('SELECT * FROM users', {username: 'memgraph', - password: 'password', - host: 'localhost', - port: '12345'} ) -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Filter specific data -```cypher -CALL migrate.arrow_flight('SELECT * FROM users', {username: 'memgraph', - password: 'password', - host: 'localhost', - port: '12345'} ) -YIELD row -WHERE row.age >= 30 -RETURN row; -``` - -#### Create nodes from migrated data -```cypher -CALL migrate.arrow_flight('SELECT id, name, age FROM users', {username: 'memgraph', - password: 'password', - host: 'localhost', - port: '12345'} ) -YIELD row -CREATE (u:User {id: row.id, name: row.name, age: row.age}); -``` - -#### Create relationships between users -```cypher -CALL migrate.arrow_flight('SELECT user1_id, user2_id FROM friendships', {username: 'memgraph', - password: 'password', - host: 'localhost', - port: '12345'} ) -YIELD row -MATCH (u1:User {id: row.user1_id}), (u2:User {id: row.user2_id}) -CREATE (u1)-[:FRIENDS_WITH]->(u2); -``` - -### `duckdb()` -With the `migrate.duckdb()` procedure, users can connect to the ** DuckDB** database and query various data sources. -List of data sources that are supported by DuckDB can be found on their [official documentation page](https://duckdb.org/docs/stable/data/data_sources.html). -The underlying implementation streams results from DuckDB to Memgraph using the `duckdb` Python Library. DuckDB is started with the in-memory mode, without any -persistence and is used just to proxy to the underlying data sources. - -{

Input:

} - -- `query: str` ➡ Table name or an SQL query. -- `setup_queries: mgp.Nullable[List[str]]` ➡ List of queries that will be executed prior to the query provided as the initial argument. -Used for setting up the connection to additional data sources. - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -{

Usage:

} - -#### Retrieve and inspect data -```cypher -CALL migrate.duckdb("SELECT * FROM 'test.parquet';") -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Filter specific data -```cypher -CALL migrate.duckdb("SELECT * FROM 'test.parquet';") -YIELD row -WHERE row.age >= 30 -RETURN row; -``` - -#### Create nodes from migrated data -```cypher -CALL migrate.duckdb("SELECT * FROM 'test.parquet';") -YIELD row -CREATE (u:User {id: row.id, name: row.name, age: row.age}); -``` - -#### Create relationships between users -```cypher -CALL migrate.duckdb("SELECT * FROM 'test.parquet';") -YIELD row -MATCH (u1:User {id: row.user1_id}), (u2:User {id: row.user2_id}) -CREATE (u1)-[:FRIENDS_WITH]->(u2); -``` - -#### Setup connection to query additional data sources -```cypher -CALL migrate.duckdb("SELECT * FROM 's3://your_bucket/your_file.parquet';", ["CREATE SECRET secret1 (TYPE s3, KEY_ID 'key', SECRET 'secret', REGION 'region');"]) -YIELD row -MATCH (u1:User {id: row.user1_id}), (u2:User {id: row.user2_id}) -CREATE (u1)-[:FRIENDS_WITH]->(u2); -``` - ---- - -### `memgraph()` - -With the `migrate.memgraph()` procedure, you can access another Memgraph instance and migrate your data to a new Memgraph instance. -The resulting nodes and edges are converted into a stream of rows which can include labels, properties, and primitives. - - -Streaming of raw node and relationship objects is not supported and users are advised to migrate all the necessary identifiers in order to recreate the same graph in Memgraph. - - -{

Input:

} - -- `label_or_rel_or_query: str` ➡ Label name (written in format `(:Label)`), relationship name (written in format `[:rel_type]`) or a plain cypher query. -- `config: mgp.Map` ➡ Connection parameters (as in `gqlalchemy.Memgraph`). Notable parameters are `host[String]`, and `port[Integer]` -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - - when retrieving nodes using the `(:Label)` syntax, row will have the following keys: `labels`, and `properties` - - when retrieving relationships using the `[:REL_TYPE]` syntax, row will have the following keys: `from_labels`, `to_labels`, `from_properties`, `to_properties`, and `edge_properties` - - when retrieving results using a plain Cypher query, row will have keys identical to the returned column names from the Cypher query - -{

Usage:

} - -#### Retrieve nodes of certain label and create them in a new Memgraph instance -```cypher -CALL migrate.memgraph('(:Person)', {host: 'localhost', port: 7687}) -YIELD row -WITH row.labels AS labels, row.properties as props -CREATE (n:labels) SET n += row.props -``` - -#### Retrieve relationships of certain type and create them in a new Memgraph instance -```cypher -CALL migrate.memgraph('[:KNOWS]', {host: 'localhost', port: 7687}) -YIELD row -WITH row.from_labels AS from_labels, - row.to_labels AS to_labels, - row.from_properties AS from_properties, - row.to_properties AS to_properties, - row.edge_properties AS edge_properties -MATCH (p1:Person {id: row.from_properties.id}) -MATCH (p2:Person {id: row.to_properties.id}) -CREATE (p1)-[r:KNOWS]->(p2) -SET r += edge_properties; -``` - -#### Retrieve information from Memgraph using an arbitrary Cypher query -```cypher -CALL migrate.memgraph('MATCH (n) RETURN count(n) as cnt', {host: 'localhost', port: 7687}) -YIELD row -RETURN row.cnt as cnt; -``` - ---- - -### `mysql()` - -With the `migrate.mysql()` procedure, you can access MySQL and migrate your data to Memgraph. -The result table is converted into a stream, and the returned rows can be used to create graph structures. - -{

Input:

} - -- `table_or_sql: str` ➡ Table name or an SQL query. -- `config: mgp.Map` ➡ Connection parameters (as in `mysql.connector.connect`). -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -{

Usage:

} - -#### Retrieve and inspect data -```cypher -CALL migrate.mysql('example_table', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Filter specific data -```cypher -CALL migrate.mysql('SELECT * FROM users', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -WHERE row.age >= 30 -RETURN row; -``` - -#### Create nodes from migrated data -```cypher -CALL migrate.mysql('SELECT id, name, age FROM users', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -CREATE (u:User {id: row.id, name: row.name, age: row.age}); -``` - -#### Create relationships between users -```cypher -CALL migrate.mysql('SELECT user1_id, user2_id FROM friendships', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -MATCH (u1:User {id: row.user1_id}), (u2:User {id: row.user2_id}) -CREATE (u1)-[:FRIENDS_WITH]->(u2); -``` - ---- - -### `neo4j()` - -With the `migrate.neo4j()` procedure, you can access Neo4j and migrate your data to Memgraph. -The resulting nodes and edges are converted into a stream of rows which can include labels, properties, and primitives. -**Streaming of raw node and relationship objects is not supported**, and users are advised to migrate all the necessary identifiers -in order to recreate the same graph in Memgraph. - -{

Input:

} - -- `label_or_rel_or_query: str` ➡ Label name (written in format `(:Label)`), relationship name (written in format `[:rel_type]`) or a plain cypher query. -- `config: mgp.Map` ➡ Connection parameters (as in `gqlalchemy.Neo4j`). Notable parameters are `host[String]` and `port[Integer]`. -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - - When retrieving nodes using the `(:Label)` syntax, row will have the following keys: `labels` and `properties`. - - When retrieving relationships using the `[:REL_TYPE]` syntax, row will have the following keys: `from_labels`, `to_labels`, `from_properties`, `to_properties` and `edge_properties`. - - When retrieving results using a plain Cypher query, row will have keys identical to the returned column names from the Cypher query. - -{

Usage:

} - -#### Retrieve nodes of certain label and create them in Memgraph -```cypher -CALL migrate.neo4j('(:Person)', {host: 'localhost', port: 7687}) -YIELD row -WITH row.labels AS labels, row.properties as props -CREATE (n:labels) SET n += row.props -``` - -#### Retrieve relationships of certain type and create them in Memgraph -```cypher -CALL migrate.neo4j('[:KNOWS]', {host: 'localhost', port: 7687}) -YIELD row -WITH row.from_labels AS from_labels, - row.to_labels AS to_labels, - row.from_properties AS from_properties, - row.to_properties AS to_properties, - row.edge_properties AS edge_properties -MATCH (p1:Person {id: row.from_properties.id}) -MATCH (p2:Person {id: row.to_properties.id}) -CREATE (p1)-[r:KNOWS]->(p2) -SET r += edge_properties; -``` - -#### Retrieve information from Neo4j using an arbitrary Cypher query -```cypher -CALL migrate.neo4j('MATCH (n) RETURN count(n) as cnt', {host: 'localhost', port: 7687}) -YIELD row -RETURN row.cnt as cnt; -``` - ---- - -### `oracle_db()` - -With the `migrate.oracle_db()` procedure, you can access Oracle DB and migrate your data to Memgraph. - -{

Input:

} - -- `table_or_sql: str` ➡ Table name or an SQL query. -- `config: mgp.Map` ➡ Connection parameters (as in `mysql.connector.connect`). -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -{

Usage:

} - -#### Retrieve and inspect data -```cypher -CALL migrate.oracle_db('example_table', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Merge nodes to avoid duplicates -```cypher -CALL migrate.oracle_db('SELECT id, name FROM companies', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'business_db'} ) -YIELD row -MERGE (c:Company {id: row.id}) -SET c.name = row.name; -``` - ---- - -### `postgresql()` - -With the `migrate.postgresql()` procedure, you can access PostgreSQL and migrate your data to Memgraph. - -{

Input:

} - -- `table_or_sql: str` ➡ Table name or an SQL query. -- `config: mgp.Map` ➡ Connection parameters (as in `mysql.connector.connect`). -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -{

Usage:

} - -#### Retrieve and inspect data -```cypher -CALL migrate.postgresql('example_table', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Create nodes for products -```cypher -CALL migrate.postgresql('SELECT product_id, name, price FROM products', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'retail_db'} ) -YIELD row -CREATE (p:Product {id: row.product_id, name: row.name, price: row.price}); -``` - -#### Establish relationships between orders and customers -```cypher -CALL migrate.postgresql('SELECT order_id, customer_id FROM orders', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'retail_db'} ) -YIELD row -MATCH (o:Order {id: row.order_id}), (c:Customer {id: row.customer_id}) -CREATE (c)-[:PLACED]->(o); -``` - ---- - -### `sql_server()` - -With the `migrate.sql_server()` procedure, you can access SQL Server and migrate your data to Memgraph. - -{

Input:

} - -- `table_or_sql: str` ➡ Table name or an SQL query. -- `config: mgp.Map` ➡ Connection parameters (as in `mysql.connector.connect`). -- `config_path` ➡ Path to a JSON file containing configuration parameters. -- `params: mgp.Nullable[mgp.Any] (default=None)` ➡ Query parameters (if applicable). - -{

Output:

} - -- `row: mgp.Map` ➡ The result table as a stream of rows. - -{

Usage:

} - -#### Retrieve and inspect data -```cypher -CALL migrate.sql_server('example_table', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'demo_db'} ) -YIELD row -RETURN row -LIMIT 5000; -``` - -#### Convert SQL table rows into graph nodes -```cypher -CALL migrate.sql_server('SELECT id, name, role FROM employees', {user: 'memgraph', - password: 'password', - host: 'localhost', - database: 'company_db'} ) -YIELD row -CREATE (e:Employee {id: row.id, name: row.name, role: row.role}); -``` - ---- - -### `s3()` - -With the `migrate.s3()` procedure, you can **access a CSV file in AWS S3**, stream the data into Memgraph, -and transform it into a **graph representation** using Cypher. The migration is using the Python `boto3` client. - -{

Input:

} - -- `file_path: str` ➡ S3 file path in the format `'s3://bucket-name/path/to/file.csv'`. -- `config: mgp.Map` ➡ AWS connection parameters. All of them are optional. - - `aws_access_key_id` - if not provided, environment variable `AWS_ACCESS_KEY_ID` will be used - - `aws_secret_access_key` - if not provided, environment variable `AWS_SECRET_ACCESS_KEY` will be used - - `region_name` - if not provided, environment variable `AWS_REGION` will be used - - `aws_session_token` - if not provided, environment variable `AWS_SESSION_TOKEN` will be used -- `config_path: str` (optional) ➡ Path to a JSON file containing AWS credentials. - -{

Output:

} - -- `row: mgp.Map` ➡ Each row from the CSV file as a structured dictionary. - -{

Usage:

} - -#### Retrieve and inspect CSV data from S3 -```cypher -CALL migrate.s3('s3://my-bucket/data.csv', {aws_access_key_id: 'your-key', - aws_secret_access_key: 'your-secret', - region_name: 'us-east-1'} ) -YIELD row -RETURN row -LIMIT 100; -``` - -#### Filter specific rows from the CSV -```cypher -CALL migrate.s3('s3://my-bucket/customers.csv', {aws_access_key_id: 'your-key', - aws_secret_access_key: 'your-secret', - region_name: 'us-west-2'} ) -YIELD row -WHERE row.age >= 30 -RETURN row; -``` - -#### Create nodes dynamically from CSV data -```cypher -CALL migrate.s3('s3://my-bucket/employees.csv', {aws_access_key_id: 'your-key', - aws_secret_access_key: 'your-secret', - region_name: 'eu-central-1'} ) -YIELD row -CREATE (e:Employee {id: row.id, name: row.name, position: row.position}); -``` - ---- - -### `servicenow()` - -With the `migrate.servicenow()` procedure, you can access [ServiceNow REST API](https://developer.servicenow.com/dev.do#!/reference/api/xanadu/rest/) and transfer your data to Memgraph. -The underlying implementation is using the [`requests` Python library] to migrate results to Memgraph. The REST API from -ServiceNow must provide results in the format `{results: []}` in order for Memgraph to stream it into result rows. - -{

Input:

} - -- `endpoint: str` ➡ ServiceNow endpoint. Users can optionally include their own query parameters to filter results. -- `config: mgp.Map` ➡ Connection parameters. Notable connection parameters are `username` and `password`, per `requests.get()` method. -- `config_path: str` ➡ Path to a JSON file containing configuration parameters. - -{

Output:

} - -- `row: mgp.Map` ➡ Each row from the CSV file as a structured dictionary. - -{

Usage:

} - -#### Retrieve and inspect CSV data from ServiceNow -```cypher -CALL migrate.servicenow('http://my_endpoint/api/data', {}) -YIELD row -RETURN row -LIMIT 100; -``` - -#### Filter specific rows from the CSV -```cypher -CALL migrate.servicenow('http://my_endpoint/api/data', {}) -YIELD row -WHERE row.age >= 30 -RETURN row; -``` - -#### Create nodes dynamically from CSV data -```cypher -CALL migrate.servicenow('http://my_endpoint/api/data', {}) -YIELD row -CREATE (e:Employee {id: row.id, name: row.name, position: row.position}); -``` +This page is kept for backwards-compatible inbound links. All content has moved to +[`cross_database`](./cross_database).