Crate apache_age

Source
Expand description

Connector to the apache age database is based on the postgres and tokio-postgres crates.

Crate source is currently in the standalone repository, but will be (eventually) merged into the apache age repository

§Features

  • pure cypher query and execution
  • field constraints creation
  • (unique) indexes creation
  • graph creation / drop
  • graph existance checks
  • postgres/tokio-postgres client usage
  • query fields builders

§Sync and async client

Both sync and async client have similar AgeClient traits. The only difference is obviously within async method declarations.

  • In order to use sync client: use apache_age::sync::{AgeClient, Client}
  • In order to use async client: use apache_age::tokio::{AgeClient, Client}

§Usage

use apache_age::sync::{AgeClient, Client};
use apache_age::{AgType, NoTls, Vertex};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Person {
    pub name: String,
    pub surname: String,
}

pub fn main() {
    // Create client
    let mut client = Client::connect_age(
        "host=localhost user=postgres password=passwd port=8081",
        NoTls,
    )
    .unwrap();

    // Create graph
    client.create_graph("my_apache_graph").unwrap();
    assert!(client.graph_exists("my_apache_graph").unwrap());

    // Using a simple postgres query to manipulate graph
    client
        .simple_query(
            &("SELECT * FROM cypher('".to_string()
                + "my_apache_graph"
                + "', $$ "
                + "CREATE(n:Person {name: 'T', surname: 'Doe'}) "
                + "RETURN n "
                + "$$) AS (v agtype)"),
        )
        .unwrap();

    // Using a normal postgres query to operate on graph
    match client.query(
        &("SELECT v FROM ag_catalog.cypher('".to_string()
            + "my_apache_graph"
            + "', $$ "
            + "MATCH(n: Person) WHERE n.name='T' "
            + "RETURN n "
            + "$$) AS (v ag_catalog.agtype)"),
        &[],
    ) {
        Err(_e) => {}
        Ok(query) => {
            for row in query {
                // Vertex usage
                let person_vertex: Vertex<Person> = row.get(0);
                assert_eq!(person_vertex.label(), "Person");
                assert_eq!(person_vertex.properties().surname, "Doe");
            }
        }
    }

    // Using execute_cypher with some input variables
    assert!(client
        .execute_cypher(
            "my_apache_graph",
            "CREATE(n: Person {name: $name, surname: $surname})",
            Some(AgType::<Person>(Person {
                name: "John".into(),
                surname: "Doe".into(),
            })),
        )
        .is_ok());

    // Using execute_cypher without some input variables
    assert!(client
        .execute_cypher::<()>(
            "my_apache_graph",
            "CREATE(n: Person {name: 'Ask', surname: 'Me'})",
            None,
        )
        .is_ok());

    // Using query_cypher without parameters
    let rows = client
        .query_cypher::<()>(
            "my_apache_graph",
            "
            MATCH (n: Person) 
            WHERE n.name = 'Ask' 
            RETURN {name: n.name, surname: n.surname}
        ",
            None,
        )
        .unwrap();

    let x: AgType<Person> = rows[0].get(0);
    assert_eq!(x.0.surname, "Me");

    // Prepared statements
    let statement = client
        .prepare_cypher(
            "my_apache_graph",
            "MATCH (n: Person) WHERE n.name = 'John' RETURN n",
            false,
        )
        .unwrap();

    let x = client.query(&statement, &[]).unwrap();
    let john_doe: Vertex<Person> = x[0].get(0);
    assert_eq!(john_doe.properties().surname, "Doe");

    // Constraints
    client
        .required_constraint("my_apache_graph", "Person", "myconstraint", "surname")
        .unwrap();

    client
        .unique_index("my_apache_graph", "Person", "myuniq", "name")
        .unwrap();

    assert!(client
        .execute_cypher::<()>(
            "my_apache_graph",
            "CREATE (p: Person { name: 'No surname' })",
            None
        )
        .is_err());

    assert!(client
        .execute_cypher::<()>(
            "my_apache_graph",
            "CREATE (p: Person { name: 'John', surname: 'Repeated name' })",
            None
        )
        .is_err());

    // Drop / destroy graph
    client.drop_graph("my_apache_graph").unwrap();
}

§Features

NameDescriptionDefault
syncpostgres based clienttrue
tokio`tokio-postgres based clienttrue
serializersserializers that can be used for query buildingfalse

Modules§

serializers
Used for query builing . Requires serializers feature
sync
Used for synchronous age connection. Requires sync feature
tokio
Used for the asynchronous age connection. Requires tokio feature

Structs§

AgType
Simple wrapper (similar to JSONB) that handles agtype serialization and deserialization
Edge
Represents edge within graph. Used during process of edge deserialization
NoTls
A MakeTlsConnect and TlsConnect implementation which simply returns an error.
Path
Vertex
Represents vertex within graph. Used during process of vertex deserialization