Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Manual in Rust

[package]
name = "manual"
version = "0.1.0"
edition = "2024"

[dependencies]
clap = { version = "4.5.38", features = ["derive"] }
falkordb = { version = "0.2.1", features = ["tokio"] }
tokio = { version = "1.52.3", features = ["full"] }
use std::collections::HashMap;

use clap::Parser;
use falkordb::{FalkorClientBuilder, FalkorConnectionInfo, FalkorValue};

#[derive(Parser, Debug)]
#[command(version, about = "Manage the Manual FalkorDB graph")]
struct Cli {
    /// Delete the graph before applying other actions.
    #[arg(long)]
    delete: bool,

    /// Add a Person node with the given name. Can be passed multiple times.
    #[arg(long = "node", value_name = "NAME", value_parser = validate_name)]
    node_names: Vec<String>,

    /// List all nodes in the graph.
    #[arg(long)]
    nodes: bool,
}

fn validate_name(name: &str) -> Result<String, String> {
    if name.is_empty() {
        return Err("name cannot be empty".to_string());
    }

    if name.chars().all(|ch| ch.is_ascii_alphanumeric()) {
        return Ok(name.to_string());
    }

    Err("name must contain only a-z, A-Z, or 0-9 characters".to_string())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();

    // Connect to FalkorDB
    let connection_info: FalkorConnectionInfo = "falkor://127.0.0.1:6379"
        .try_into()
        .expect("Invalid connection info");

    let client = FalkorClientBuilder::new_async()
        .with_connection_info(connection_info)
        .build()
        .await?;

    let mut graph = client.select_graph("Manual");

    if cli.delete {
        graph.delete().await?;
        println!("Deleted graph {}", graph.graph_name());
    }

    for name in cli.node_names {
        let mut params = HashMap::new();
        params.insert("name".to_string(), format!("'{name}'"));

        graph
            .query("CREATE (:Person {name: $name})")
            .with_params(&params)
            .execute()
            .await?;

        println!("Added Person node with name {name}");
    }

    if cli.nodes {
        let mut result = graph.query("MATCH (n) RETURN n").execute().await?;

        if result.data.is_empty() {
            println!("No nodes found");
        } else {
            while let Some(row) = result.data.next() {
                for value in row {
                    match value {
                        FalkorValue::Node(node) => println!("{node:?}"),
                        other => println!("{other:?}"),
                    }
                }
            }
        }
    }


    Ok(())
}