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§

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

Structs§

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