Rust搜索引擎库meilisearch-sdk的使用:快速集成全文搜索功能到Rust应用

Rust搜索引擎库meilisearch-sdk的使用:快速集成全文搜索功能到Rust应用

Meilisearch-Rust

Meilisearch Rust SDK是Rust开发者使用的Meilisearch API客户端。Meilisearch是一个开源搜索引擎。

安装

在您的Cargo.toml中添加以下内容:

[dependencies]
meilisearch-sdk = "0.29.1"

可选依赖项:

futures = "0.3" # 如果您不使用异步运行时,可以阻塞异步函数
serde = { version = "1.0", features = ["derive"] }

快速入门

添加文档

use meilisearch_sdk::client::*;
use serde::{Serialize, Deserialize};
use futures::executor::block_on;

#[derive(Serialize, Deserialize, Debug)]
struct Movie {
    id: usize,
    title: String,
    genres: Vec<String>,
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    // 创建一个客户端(不发送任何请求,所以不会失败)
    let client = Client::new(MEILISEARCH_URL, Some(MEILISEARCH_API_KEY)).unwrap();

    // 索引是存储文档的地方
    let movies = client.index("movies");

    // 在索引中添加一些电影。如果索引'movies'不存在,Meilisearch会在第一次添加文档时创建它
    movies.add_documents(&[
        Movie { id: 1, title: String::from("Carol"), genres: vec!["Romance".to_string(), "Drama".to_string()] },
        Movie { id: 2, title: String::from("Wonder Woman"), genres: vec!["Action".to_string(), "Adventure".to_string()] },
        Movie { id: 3, title: String::from("Life of Pi"), genres: vec!["Adventure".to_string(), "Drama".to_string()] },
        Movie { id: 4, title: String::from("Mad Max"), genres: vec!["Adventure".to_string(), "Science Fiction".to_string()] },
        Movie { id: 5, title: String::from("Moana"), genres: vec!["Fantasy".to_string(), "Action".to_string()] },
        Movie { id: 6, title: String::from("Philadelphia"), genres: vec!["Drama".to_string()] },
    ], Some("id")).await.unwrap();
}

基本搜索

// Meilisearch具有容错能力:
println!("{:?}", client.index("movies_2").search().with_query("caorl").execute::<Movie>().await.unwrap().hits);

输出:

[Movie { id: 1, title: String::from("Carol"), genres: vec!["Romance", "Drama"] }]

自定义搜索

let search_result = client.index("movies_3")
  .search()
  .with_query("phil")
  .with_attributes_to_highlight(Selectors::Some(&["*"]))
  .execute::<Movie>()
  .await
  .unwrap();
println!("{:?}", search_result.hits);

带过滤器的自定义搜索

如果要启用过滤,必须将您的属性添加到filterableAttributes索引设置中。

let filterable_attributes = [
    "id",
    "genres",
];
client.index("movies_4").set_filterable_attributes(&filterable_attributes).await.unwrap();

然后,您可以执行搜索:

let search_result = client.index("movies_5")
  .search()
  .with_query("wonder")
  .with_filter("id > 1 AND genres = Action")
  .execute::<Movie>()
  .await
  .unwrap();
println!("{:?}", search_result.hits);

完整示例

use meilisearch_sdk::client::*;
use serde::{Serialize, Deserialize};
use tokio;

#[derive(Serialize, Deserialize, Debug)]
struct Movie {
    id: usize,
    title: String,
    genres: Vec<String>,
}

#[tokio::main]
async fn main() {
    // 初始化客户端
    let client = Client::new("http://localhost:7700", Some("masterKey")).unwrap();
    
    // 获取或创建索引
    let movies = client.index("movies");
    
    // 添加文档
    movies.add_documents(&[
        Movie { id: 1, title: "Carol".to_string(), genres: vec!["Romance".to_string(), "Drama".to_string()] },
        Movie { id: 2, title: "Wonder Woman".to_string(), genres: vec!["Action".to_string(), "Adventure".to_string()] },
        Movie { id: 3, title: "Life of Pi".to_string(), genres: vec!["Adventure".to_string(), "Drama".to_string()] },
    ], Some("id")).await.unwrap();
    
    // 简单搜索
    let result = movies.search()
        .with_query("wonder")
        .execute::<Movie>()
        .await
        .unwrap();
    
    println!("搜索结果: {:?}", result.hits);
    
    // 设置可过滤属性
    movies.set_filterable_attributes(&["genres"]).await.unwrap();
    
    // 带过滤器的搜索
    let filtered_result = movies.search()
        .with_query("woman")
        .with_filter("genres = Action")
        .execute::<Movie>()
        .await
        .unwrap();
    
    println!("过滤后的结果: {:?}", filtered_result.hits);
}

这个示例展示了如何:

  1. 初始化Meilisearch客户端
  2. 创建/获取索引
  3. 添加文档到索引
  4. 执行基本搜索
  5. 设置可过滤属性
  6. 执行带过滤器的搜索

您可以根据需要调整搜索参数和过滤器条件来满足您的应用需求。


1 回复

meilisearch-sdk使用指南:快速集成全文搜索功能到Rust应用

介绍

meilisearch-sdk是一个Rust客户端库,用于与MeiliSearch搜索引擎交互。MeiliSearch是一个开源的、超快速的搜索引擎,可以轻松地为你的应用添加强大的搜索功能。

主要特性

  • 简单易用的API
  • 即时搜索(输入时实时显示结果)
  • 高度可定制(相关性排序、过滤、分面等)
  • 支持多种数据类型
  • 轻量级且快速

安装

在Cargo.toml中添加依赖:

[dependencies]
meilisearch-sdk = "0.20"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 连接到MeiliSearch服务器

use meilisearch_sdk::{client::*, indexes::*};

#[tokio::main]
async fn main() {
    // 连接到本地MeiliSearch实例
    let client = Client::new("http://localhost:7700", "masterKey");
    
    // 检查服务器健康状态
    if let Ok(health) = client.health().await {
        println!("Server is healthy: {:?}", health);
    }
}

2. 创建索引并添加文档

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Movie {
    id: String,
    title: String,
    genres: Vec<String>,
    year: i32,
}

async fn create_index(client: &Client) {
    // 创建或获取索引
    let movies = client.index("movies");
    
    // 定义文档
    let documents = vec![
        Movie {
            id: "1".to_string(),
            title: "The Shawshank Redemption".to_string(),
            genres: vec!["Drama".to_string(), "Crime".to_string()],
            year: 1994,
        },
        Movie {
            id: "2".to_string(),
            title: "The Godfather".to_string(),
            genres: vec!["Crime".to_string(), "Drama"].to_string()],
            year: 1972,
        },
    ];
    
    // 添加文档到索引
    let task = movies.add_documents(&documents, Some("id")).await;
    match task {
        Ok(task) => println!("Documents added successfully: {:?}", task),
        Err(e) => eprintln!("Error adding documents: {}", e),
    }
}

3. 执行搜索

async fn search_movies(client: &Client) {
    let movies = client.index("movies");
    
    // 简单搜索
    let results = movies.search()
        .with_query("shawshank")
        .execute::<Movie>()
        .await
        .unwrap();
    
    println!("Search results for 'shawshank':");
    for hit in results.hits {
        println!("- {} ({})", hit.result.title, hit.result.year);
    }
    
    // 带过滤的搜索
    let filtered_results = movies.search()
        .with_query("crime")
        .with_filter("year > 1990")
        .execute::<Movie>()
        .await
        .unwrap();
    
    println!("\nFiltered results (crime movies after 1990):");
    for hit in filtered_results.hits {
        println!("- {} ({})", hit.result.title, hit.result.year);
    }
}

高级功能

1. 配置索引设置

async fn configure_index(client: &Client) {
    let movies = client.index("movies");
    
    // 设置搜索属性
    let settings = Settings::new()
        .with_searchable_attributes(["title", "genres"])
        .with_filterable_attributes(["year", "genres"]);
    
    movies.set_settings(&settings).await.unwrap();
}

2. 同义词和停用词

async fn configure_synonyms(client: &Client) {
    let movies = client.index("movies");
    
    // 设置同义词
    let synonyms = json!({
        "flick": ["movie", "film"],
        "movie": ["flick", "film"],
        "film": ["flick", "movie"]
    });
    
    movies.set_synonyms(&synonyms).await.unwrap();
}

3. 分面搜索

async fn facet_search(client: &Client) {
    let movies = client.index("movies");
    
    // 获取所有流派的分面统计
    let results = movies.search()
        .with_query("")
        .with_facets(["genres"])
        .execute::<Movie>()
        .await
        .unwrap();
    
    if let Some(facets) = results.facet_distribution {
        if let Some(genres) = facets.get("genres") {
            println!("Genre distribution:");
            for (genre, count) in genres {
                println!("- {}: {}", genre, count);
            }
        }
    }
}

完整示例代码

use meilisearch_sdk::{client::*, indexes::*, settings::Settings};
use serde_json::json;

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Movie {
    id: String,
    title: String,
    genres: Vec<String>,
    year: i32,
}

#[tokio::main]
async fn main() {
    // 1. 连接到服务器
    let client = Client::new("http://localhost:7700", "masterKey");
    
    // 2. 创建索引并添加文档
    let movies = client.index("movies");
    
    let documents = vec![
        Movie {
            id: "1".to_string(),
            title: "The Shawshank Redemption".to_string(),
            genres: vec!["Drama".to_string(), "Crime".to_string()],
            year: 1994,
        },
        Movie {
            id: "2".to_string(),
            title: "The Godfather".to_string(),
            genres: vec!["Crime".to_string(), "Drama".to_string()],
            year: 1972,
        },
    ];
    
    movies.add_documents(&documents, Some("id")).await.unwrap();
    
    // 3. 配置索引
    let settings = Settings::new()
        .with_searchable_attributes(["title", "genres"])
        .with_filterable_attributes(["year", "genres"]);
    
    movies.set_settings(&settings).await.unwrap();
    
    // 4. 执行搜索
    let results = movies.search()
        .with_query("shawshank")
        .execute::<Movie>()
        .await
        .unwrap();
    
    println!("Search results:");
    for hit in results.hits {
        println!("- {} ({})", hit.result.title, hit.result.year);
    }
    
    // 5. 分面搜索
    let facet_results = movies.search()
        .with_query("")
        .with_facets(["genres"])
        .execute::<Movie>()
        .await
        .unwrap();
    
    if let Some(facets) = facet_results.facet_distribution {
        if let Some(genres) = facets.get("genres") {
            println!("\nGenre distribution:");
            for (genre, count) in genres {
                println!("- {}: {}", genre, count);
            }
        }
    }
}

总结

meilisearch-sdk为Rust应用提供了简单高效的方式来集成MeiliSearch的强大搜索功能。通过这个库,你可以快速实现全文搜索、过滤、分面搜索等高级功能,同时保持代码的简洁性和高性能。

回到顶部