# Neo4j Lineage Verification Guide

Use this guide to confirm that your plants and LINEAGE relationships have been imported correctly into Neo4j. Save this file as `neo4j_lineage_check.md` for future reference.

---

## 1. Open the Neo4j Browser

1. **Ensure Neo4j is running.**
   In a Docker‐Compose setup, Neo4j is typically exposed at:

   ```
   http://localhost:7474
   ```
2. **Log in** with your Neo4j credentials (e.g., username `neo4j`, password as configured).

Once logged in, you can execute Cypher commands in the query pane on the left.

---

## 2. Verify That Your `Plant` Nodes Exist

Before checking relationships, confirm that nodes were created:

```cypher
MATCH (p:Plant)
RETURN p.uuid AS uuid, p.name AS common_name
LIMIT 20;
```

* This query will return up to 20 plant nodes with their `uuid` and `name` properties.
* If you see your imported plants here, it means the nodes exist in the database.

---

## 3. Check Direct Parent→Child LINEAGE Pairs

To list all direct child→parent relationships:

```cypher
MATCH (child:Plant)-[:LINEAGE]->(parent:Plant)
RETURN child.uuid AS child_uuid, parent.uuid AS parent_uuid
LIMIT 50;
```

* Each row represents one `(:Plant)-[:LINEAGE]->(:Plant)` relationship.
* `child_uuid` is the UUID of the child node, and `parent_uuid` is the UUID of its direct parent.

---

## 4. Look Up a Specific Plant by UUID or Name

If you know a particular plant’s UUID, you can confirm its properties:

```cypher
MATCH (p:Plant {uuid: "YOUR_UUID_HERE"})
RETURN p.uuid AS uuid, p.name AS common_name, p.scientific_name AS sci_name;
```

Alternatively, if you only know the common name:

```cypher
MATCH (p:Plant)
WHERE p.name = "Common Name Here"
RETURN p.uuid AS uuid, p.name AS common_name, p.scientific_name AS sci_name;
```

This helps you find the exact UUID or check that the `name` and `scientific_name` properties were stored correctly.

---

## 5. Show Children of a Given Parent

To list all direct children of a specific parent by UUID:

```cypher
MATCH (parent:Plant {uuid: "PARENT_UUID_HERE"})<-[:LINEAGE]-(child:Plant)
RETURN child.uuid AS child_uuid, child.name AS child_name;
```

* This returns every plant node that points to the specified `parent_uuid` via a `LINEAGE` relationship.

---

## 6. Visualize a Subtree Around One Node

To visualize a parent node and its children in graph form:

```cypher
MATCH subtree = (parent:Plant {uuid: "PARENT_UUID_HERE"})<-[:LINEAGE]-(child:Plant)
RETURN subtree;
```

* Switch to the “Graph” view in the Neo4j browser to see a node for the parent with arrows pointing to each child.

---

## 7. Walk the Full Ancestor Chain (Multi‐Level)

If you want to see all ancestors of a given child, use a variable‐length pattern:

```cypher
MATCH path = (desc:Plant {uuid: "CHILD_UUID_HERE"})-[:LINEAGE*1..]->(anc:Plant)
RETURN path;
```

* `[:LINEAGE*1..]` indicates “follow one or more consecutive `LINEAGE` relationships upward.”
* In “Graph” view, Neo4j will display the entire chain from child → parent → grandparent → …

To return just the list of ancestor UUIDs:

```cypher
MATCH (start:Plant {uuid: "CHILD_UUID_HERE"})-[:LINEAGE*1..]->(anc:Plant)
RETURN DISTINCT anc.uuid AS ancestor_uuid;
```

---

## 8. Show All Descendants of a Given Parent

To find all descendants (children, grandchildren, etc.) of a root node:

```cypher
MATCH (root:Plant {uuid: "ROOT_UUID_HERE"})<-[:LINEAGE*]-(desc:Plant)
RETURN desc.uuid AS descendant_uuid, desc.name AS descendant_name;
```

* The pattern `[:LINEAGE*]` (with no lower bound specified) matches zero or more hops.
* To visualize the full descendant tree:

  ```cypher
  MATCH subtree = (root:Plant {uuid: "ROOT_UUID_HERE"})<-[:LINEAGE*]-(desc:Plant)
  RETURN subtree;
  ```

  Then switch to “Graph” view.

---

## 9. Combining Queries for a Full Walk‐Through

1. **List a few plants** (to copy a known UUID):

   ```cypher
   MATCH (p:Plant)
   RETURN p.uuid AS uuid, p.name AS common_name
   LIMIT 10;
   ```
2. **Pick one UUID** (e.g. `"2ee2e0e7-69de-4b8f-abfe-4ed973c3d760"`).
3. **Show its direct children**:

   ```cypher
   MATCH (p:Plant {uuid: "2ee2e0e7-69de-4b8f-abfe-4ed973c3d760"})<-[:LINEAGE]-(child:Plant)
   RETURN child.uuid AS child_uuid, child.name AS child_name;
   ```
4. **Show its parent** (if any):

   ```cypher
   MATCH (p:Plant {uuid: "8b1059c8-8dd3-487a-af19-1eb548788e87"})-[:LINEAGE]->(parent:Plant)
   RETURN parent.uuid AS parent_uuid, parent.name AS parent_name;
   ```
5. **Get the full ancestor chain** of that child:

   ```cypher
   MATCH path = (c:Plant {uuid: "8b1059c8-8dd3-487a-af19-1eb548788e87"})-[:LINEAGE*1..]->(anc:Plant)
   RETURN path;
   ```
6. **Get the full descendant tree** of that parent:

   ```cypher
   MATCH subtree = (root:Plant {uuid: "2ee2e0e7-69de-4b8f-abfe-4ed973c3d760"})<-[:LINEAGE*]-(desc:Plant)
   RETURN subtree;
   ```

---

## 10. Checking via Python (Optional)

If you prefer to script these checks using the Neo4j Bolt driver from Python, here’s a quick example:

```python
from neo4j import GraphDatabase

uri      = "bolt://localhost:7687"
auth     = ("neo4j", "your_password")
driver   = GraphDatabase.driver(uri, auth=auth)

def print_lineage(tx, plant_uuid):
    # Show direct parent
    result = tx.run(
        "MATCH (c:Plant {uuid:$u})-[:LINEAGE]->(p:Plant) "
        "RETURN p.uuid AS parent_uuid, p.name AS parent_name",
        u=plant_uuid
    )
    for row in result:
        print(f"Parent of {plant_uuid}: {row['parent_uuid']} ({row['parent_name']})")

    # Show all ancestors
    result2 = tx.run(
        "MATCH path = (c:Plant {uuid:$u})-[:LINEAGE*1..]->(anc:Plant) "
        "RETURN [n IN nodes(path) | n.uuid] AS all_uuids",
        u=plant_uuid
    )
    for row in result2:
        print("Ancestor chain UUIDs:", row["all_uuids"])

with driver.session() as session:
    session.read_transaction(print_lineage, "8b1059c8-8dd3-487a-af19-1eb548788e87")

driver.close()
```

* Install `neo4j` Python package if needed:

  ```bash
  pip install neo4j
  ```
* Adjust the `uri` and `auth` values to match your Neo4j setup.

---

## 11. Summary of Key Cypher Queries

* **List all plants (sample):**

  ```cypher
  MATCH (p:Plant)
  RETURN p.uuid AS uuid, p.name AS common_name
  LIMIT 20;
  ```

* **List direct parent→child relationships:**

  ```cypher
  MATCH (child:Plant)-[:LINEAGE]->(parent:Plant)
  RETURN child.uuid AS child_uuid, parent.uuid AS parent_uuid;
  ```

* **List direct children of a parent:**

  ```cypher
  MATCH (parent:Plant {uuid:"PARENT_UUID"})<-[:LINEAGE]-(child:Plant)
  RETURN child.uuid AS child_uuid, child.name AS child_name;
  ```

* **List direct parent of a child:**

  ```cypher
  MATCH (child:Plant {uuid:"CHILD_UUID"})-[:LINEAGE]->(parent:Plant)
  RETURN parent.uuid AS parent_uuid, parent.name AS parent_name;
  ```

* **Visualize parent + children subgraph:**

  ```cypher
  MATCH subtree = (parent:Plant {uuid:"PARENT_UUID"})<-[:LINEAGE]-(child:Plant)
  RETURN subtree;
  ```

* **Full ancestor chain for a child:**

  ```cypher
  MATCH path = (c:Plant {uuid:"CHILD_UUID"})-[:LINEAGE*1..]->(anc:Plant)
  RETURN path;
  ```

* **Full descendant tree for a parent:**

  ```cypher
  MATCH subtree = (root:Plant {uuid:"PARENT_UUID"})<-[:LINEAGE*]-(desc:Plant)
  RETURN subtree;
  ```

---

### Usage Tips

* **Switch between “Table” and “Graph” views** in the Neo4j Browser to see raw data vs. visual graph.
* Use `LIMIT` when you only want a quick preview of results.
* To filter by partial names, you can do:

  ```cypher
  MATCH (p:Plant)
  WHERE toLower(p.name) CONTAINS toLower("baltic")
  RETURN p.uuid, p.name;
  ```
* Remember to enclose string literals in double quotes (`"..."`) and escape any internal quotes if needed.

Keep this guide handy for whenever you need to verify or debug your Neo4j lineage data!
