Rust Neo4j数据库驱动宏库neo4rs-macros的使用,高效实现Rust与Neo4j图数据库的无缝交互

Rust Neo4j数据库驱动宏库neo4rs-macros的使用,高效实现Rust与Neo4j图数据库的无缝交互

安装

在项目目录中运行以下Cargo命令:

cargo add neo4rs-macros

或者在Cargo.toml中添加以下行:

neo4rs-macros = "0.3.0"

使用示例

以下是一个完整的示例,展示如何使用neo4rs-macros与Neo4j数据库进行交互:

use neo4rs::*;
use neo4rs_macros::*;

#[derive(GraphEntity, Debug)]
struct Person {
    #[id]
    id: i64,
    name: String,
    age: i32,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接Neo4j数据库
    let uri = "bolt://localhost:7687";
    let user = "neo4j";
    let pass = "password";
    let graph = Graph::new(uri, user, pass).await?;
    
    // 创建节点
    let person = Person {
        id: 0,  // 新节点会自动分配ID
        name: "Alice".to_string(),
        age: 30,
    };
    
    // 使用宏生成的查询方法
    let query = person.create_query();
    graph.run(query).await?;
    
    // 查询节点
    let query = Person::match_query().filter("name = 'Alice'");
    let mut result = graph.execute(query).await?;
    
    while let Ok(Some(row)) = result.next().await {
        let person: Person = row.try_into()?;
        println!("Found person: {:?}", person);
    }
    
    Ok(())
}

功能说明

  1. #[derive(GraphEntity)] 宏自动为结构体生成Neo4j节点映射
  2. #[id] 属性标记ID字段,用于节点识别
  3. 自动生成CRUD查询方法:
    • create_query() - 创建节点
    • match_query() - 查询节点
    • update_query() - 更新节点
    • delete_query() - 删除节点

完整示例代码

以下是一个更完整的示例,包含更多CRUD操作:

use neo4rs::*;
use neo4rs_macros::*;

// 定义Person节点
#[derive(GraphEntity, Debug, Clone)]
struct Person {
    #[id]
    id: i64,
    name: String,
    age: i32,
    email: Option<String>,  // 可选字段
}

// 定义Movie节点
#[derive(GraphEntity, Debug)]
struct Movie {
    #[id]
    id: i64,
    title: String,
    year: i32,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接Neo4j数据库
    let graph = Graph::new("bolt://localhost:7687", "neo4j", "password").await?;

    // 1. 创建节点
    let person = Person {
        id: 0,  // 新节点ID设为0,数据库会自动分配
        name: "Bob".to_string(),
        age: 35,
        email: Some("bob@example.com".to_string()),
    };
    
    let movie = Movie {
        id: 0,
        title: "The Matrix".to_string(),
        year: 1999,
    };

    // 创建Person节点
    graph.run(person.create_query()).await?;
    
    // 创建Movie节点
    graph.run(movie.create_query()).await?;

    // 2. 查询节点
    let query = Person::match_query()
        .filter("name = 'Bob' AND age > 30");
    let mut result = graph.execute(query).await?;
    
    while let Ok(Some(row)) = result.next().await {
        let person: Person = row.try_into()?;
        println!("查询到Person: {:?}", person);
    }

    // 3. 更新节点
    let mut person_to_update = Person {
        id: 1,  // 假设这是数据库中已存在的ID
        name: "Bob".to_string(),
        age: 36,  // 更新年龄
        email: Some("new-email@example.com".to_string()),
    };
    
    graph.run(person_to_update.update_query()).await?;

    // 4. 删除节点
    let person_to_delete = Person {
        id: 1,  // 要删除的节点ID
        name: "".to_string(),  // 这些字段在删除时不需要
        age: 0,
        email: None,
    };
    
    graph.run(person_to_delete.delete_query()).await?;

    // 5. 创建关系
    let relation_query = query("MATCH (p:Person {name: $name}), (m:Movie {title: $title}) 
                              CREATE (p)-[r:ACTED_IN {role: $role}]->(m)")
        .param("name", "Bob")
        .param("title", "The Matrix")
        .param("role", "Neo");
    
    graph.run(relation_query).await?;

    Ok(())
}

功能说明

  1. 支持定义复杂的节点结构,包含可选字段
  2. 支持完整的CRUD操作
  3. 支持关系创建和查询
  4. 自动生成的查询方法可以与原生查询混合使用
  5. 支持异步操作,与Tokio运行时完美集成

许可证

MIT License


1 回复

Rust Neo4j数据库驱动宏库neo4rs-macros使用指南

介绍

neo4rs-macros是一个Rust宏库,它为neo4rs(Rust的Neo4j驱动)提供了过程宏支持,可以更高效、更直观地实现Rust与Neo4j图数据库的交互。通过使用宏,开发者可以用更简洁的语法实现节点、关系的定义和查询操作。

主要特性

  • 简化节点和关系的定义
  • 自动类型转换
  • 减少样板代码
  • 更直观的Cypher查询构建

安装

在Cargo.toml中添加依赖:

[dependencies]
neo4rs = "0.7"
neo4rs-macros = "0.3"
tokio = { version = "1.0", features = ["full"] }

完整示例代码

use neo4rs::*;
use neo4rs_macros::{Node, Relation, query};
use tokio;

// 定义节点结构
#[derive(Node, Debug)]
struct Person {
    id: i64,
    name: String,
    age: i32,
}

#[derive(Node, Debug)]
struct Movie {
    id: i64,
    title: String,
    year: i32,
}

// 定义关系结构
#[derive(Relation, Debug)]
struct ActedIn {
    roles: Vec<String>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 初始化Neo4j连接
    let uri = "127.0.0.1:7687";
    let user = "neo4j";
    let pass = "password";
    let graph = Graph::new(&uri, user, pass).await?;
    
    // 2. 创建节点
    let person = Person {
        id: 1,
        name: "Keanu Reeves".to_string(),
        age: 57,
    };
    
    query!(
        graph,
        "CREATE (p:Person {id: $id, name: $name, age: $age})",
        person
    ).run().await?;
    
    // 3. 查询节点
    let name = "Keanu Reeves";
    let people: Vec<Person> = query!(
        graph,
        "MATCH (p:Person {name: $name}) RETURN p",
        name
    ).fetch().await?;
    
    for person in people {
        println!("查询到人员: {} (年龄: {})", person.name, person.age);
    }
    
    // 4. 创建关系和节点
    let matrix = Movie {
        id: 1,
        title: "The Matrix".to_string(),
        year: 1999,
    };
    
    let acted_in = ActedIn {
        roles: vec!["Neo".to_string()],
    };
    
    query!(
        graph,
        r#"
        CREATE (p:Person {id: $p.id, name: $p.name, age: $p.age})
        CREATE (m:Movie {id: $m.id, title: $m.title, year: $m.year})
        CREATE (p)-[r:ACTED_IN {roles: $r.roles}]->(m)
        "#,
        p = person,
        m = matrix,
        r = acted_in
    ).run().await?;
    
    // 5. 高级查询
    let movie_title = "The Matrix";
    
    #[derive(Debug)]
    struct CastMember {
        person: Person,
        roles: Vec<String>,
    }
    
    let cast: Vec<CastMember> = query!(
        graph,
        r#"
        MATCH (p:Person)-[r:ACTED_IN]->(m:Movie {title: $title})
        RETURN p as person, r.roles as roles
        "#,
        title = movie_title
    ).fetch().await?;
    
    for member in cast {
        println!("{} 在 {} 中扮演的角色: {:?}", member.person.name, movie_title, member.roles);
    }
    
    Ok(())
}

代码说明

  1. 首先定义了两种节点类型(PersonMovie)和一种关系类型(ActedIn)
  2. 使用tokio::main宏创建异步运行时
  3. 初始化Neo4j数据库连接
  4. 演示了CRUD操作:
    • 创建Person节点
    • 查询Person节点
    • 创建Movie节点和ACTED_IN关系
    • 高级查询获取电影演员信息

注意事项

  1. 确保Neo4j数据库服务已启动
  2. 宏展开后的代码依赖于neo4rs库,需要确保版本兼容
  3. 复杂查询可能需要手动编写Cypher语句
  4. 在生产环境中使用时应添加适当的错误处理和日志记录

性能建议

  1. 批量操作时使用事务
  2. 对于大量数据,考虑使用UNWIND批量创建
  3. 合理使用索引提高查询性能

通过neo4rs-macros,Rust开发者可以更高效地与Neo4j图数据库交互,减少样板代码,提高开发效率。

回到顶部