Search code examples
pythonmemgraphdb

Handling unique constraints in gqlalchemy OGM vs Cypher for supply chain nodes


I'm experiencing some confusion with the usage of gqlalchemy's OGM and Cypher queries, specifically regarding the enforcement of unique constraints on node attributes.

I want to model supply chain entities as nodes, enforcing unique identifiers for each entity. When using gqlalchemy's OGM, I can create a node with an existing unique identifier without encountering an error - the node is created only once in the database. When executing a similar creation via a Cypher query rightly triggers a unique constraint violation error.

My Python code is:

from typing import Optional
from gqlalchemy import Memgraph, Node, Field

db_connection = Memgraph()
db_connection.drop_database()

class SupplyEntity(Node):
    entity_id: str
    entity_name: str

class Manufacturer(SupplyEntity):
    entity_id: str = Field(unique=True, db=db_connection)
    entity_name: Optional[str] = Field(exists=True, db=db_connection)
    production_capacity: Optional[str]

Manufacturer(entity_id="M001", entity_name="AcmeCorp").save(db_connection)
print("Registered manufacturer AcmeCorp once")

Manufacturer(entity_id="M001", entity_name="AcmeCorp").save(db_connection)
print("Attempted to register AcmeCorp again")

SupplyEntity(entity_id="M001", entity_name="NewCo").save(db_connection)
print("Registered another entity with the same ID M001")

try:
    result = db_connection.execute(
        """
        CREATE (:Manufacturer:SupplyEntity {entity_id: "M001", entity_name: "AcmeCorp"});
        """
    )
except Exception as error:
    print("Direct Cypher query failed with error: ", error)
    Manufacturer(entity_id="M001", entity_name="AcmeCorp").save(db_connection)  # this works
    print("OGM approach succeeded despite expected constraint violation")

And in my terminal I can see:

Registered manufacturer AcmeCorp once
Attempted to register AcmeCorp again
Registered another entity with the same ID M001
Direct Cypher query failed with error: Unable to commit due to unique constraint violation on :Manufacturer(entity_id)
OGM approach succeeded despite expected constraint violation

Solution

  • I've recently encountered a similar question, the reason for this is after creating your first Manufacturer node, the database loads the node, checks if it exists and saves a node if it doesn't exist.

    Then you run your second query which again checks the database based on the id that has uniqueness constraint and realizes the node already exists, it updates it if necessary, but it doesn't try to create it and therefore you don't get an error on constraint violation.

    After that, you run your third query which creates SupplyEntity with the same id as the previous Manufacturer because your SupplyEntity label doesn't have a uniqueness constraint.

    Lastly, when running a Cypher query

    CREATE (:Manufacturer:SupplyEntity {entity_id: "M001", entity_name: "AcmeCorp"});
    

    you receive a uniqueness constraint error because it immediately tries to CREATE without checking if the node exists in the database beforehand.