Tutorial: Cross-Model Queries

Polypheny is a powerful tool that allows you to manage and query data stored in different models seamlessly. This tutorial will walk you through creating a simple toy example to illustrate how to perform cross-model queries in Polypheny.

Introduction

This tutorial will focus on the logical data model, leaving out the details of physical storage. Polypheny allows you to perform queries across different storage models seamlessly, regardless of where the data is stored. While the underlying storage architecture doesn’t impact the ability to perform queries, using optimized stores can significantly improve performance.

In this tutorial, we will create a simple toy example of an e-commerce data management scenario. We will manage product data in a document model, user data in a graph model, and order data in a relational model.

Setting Up Namespaces

First, create three namespaces: “crm” for graph data, “shop” for document data, and “sales” for relational data. This can be done using the UI or with the following SQL query:

CREATE GRAPH NAMESPACE "crm";
CREATE DOCUMENT NAMESPACE "shop";
CREATE RELATIONAL NAMESPACE "sales";

Creating Entities and Adding Data

Next, let’s create a “products” collection in the “shop” namespace. We can do this either using the UI or using an MQL query:

use shop;
db.createCollection("products");
db.products.insertMany([
   { name: "Product 1", price: 19.99, details: { weight: "1kg", color: "Red" } },
   { name: "Product 2", price: 22.50, details: { weight: "2kg", color: "Blue" } }
]);

Next, we create the order table using a SQL query and insert some data:

CREATE TABLE sales.orders (
    order_id INTEGER PRIMARY KEY,
    user_id INTEGER,
    product_name VARCHAR(255),
    quantity INTEGER
);

INSERT INTO sales.orders (order_id, user_id, product_name, quantity) VALUES
(1, 1, 'Product 1', 2),
(2, 2, 'Product 2', 1);

Last but not least, we populate the user namespace with some graph data using Cypher:

use crm;
CREATE (user1:customer {id: 1, name: 'Alice'}),
       (user2:customer {id: 2, name: 'Bob'}),
       (user1)-[:KNOWS]->(user2);

Simple Cross-Model Queries

Now, let’s perform queries that span across different models. We call it a cross-model query if at least two data models are involved. This is the case if an entity is accessed using a query language based on a different data model than the entity.

Query Document Data Using SQL

Retrieve product information using SQL from the document model:

SELECT 
  JSON_VALUE(d, 'lax $.name') AS name,
  JSON_VALUE(d, 'lax $.price') AS price,
  JSON_VALUE(d, 'lax $.details.weight') AS weight,
  JSON_VALUE(d, 'lax $.details.color') AS color
FROM shop.products;

Query Graph Data Using SQL

Retrieve user information using SQL from the graph model:

SELECT JSON_VALUE(properties, 'lax $.name') AS user_name
FROM crm.customer;

Query Relational Data Using Cypher

Retrieve order information using Cypher from the relational model:

use sales;
MATCH (o:orders)
RETURN o.order_id, o.user_id, o.product_name, o.quantity;

To view as graph, return the whole graph instead of projecting:

use sales;
MATCH (o:orders)
RETURN o;

Query Document Data Using Cypher

Retrieve product details using Cypher from the document model:

use shop;
MATCH (p:products)
RETURN p.name, p.price, p.details;

Query Graph Data Using MongoDB

Retrieve user relationships using MongoDB query language from the graph model:

use crm;
db.customer.find({});

Combine From Different Namespaces

Polypheny also supports combining (e.g., joining) data maintained according to different data models.

Combining Relational and Document Data

If we want to find orders along with product details maintained in the document model:

SELECT 
  o.order_id, 
  o.user_id, 
  o.product_name, 
  o.quantity, 
  JSON_VALUE(p.d, 'lax $.price') AS price
FROM sales.orders o
JOIN shop.products p
ON o.product_name = JSON_VALUE(p.d, 'lax $.name');

This query combines order information from the relational model with product information from the document model.

Combining Relational and Graph Data

We can also join with the customers maintained in a graph. This is handy if we want to find the customers who placed orders along with their order details:

SELECT 
  o.order_id,
  JSON_VALUE(c.properties, 'lax $.name') AS customer_name,
  o.product_name,
  o.quantity
FROM sales.orders o
JOIN crm.customer c
ON o.user_id = CAST(JSON_VALUE(c.properties, 'lax $.id') AS INTEGER)

Combining Data From All Three Namespaces

Now let’s combine data from all three namespaces. We want to find user names, their orders, and product details:

SELECT 
  JSON_VALUE(c.properties, 'lax $.name') AS customer_name, 
  o.order_id, 
  o.product_name,
  o.quantity, 
  JSON_VALUE(p.d, 'lax $.price') AS price
FROM sales.orders o
JOIN crm.customer c
ON o.user_id = CAST(JSON_VALUE(c.properties, 'lax $.id') AS INTEGER)
JOIN shop.products p
ON o.product_name = JSON_VALUE(p.d, 'lax $.name');

This comprehensive query integrates user information from the graph model, order information from the relational model, and product details from the document model, demonstrating the power of Polypheny’s cross-model query capabilities.

© Polypheny GmbH. All Rights Reserved.