Skip to main content

Crate seekstorm_client_rs

Crate seekstorm_client_rs 

Source
Expand description

§seekstorm_client_rs

SeekStorm is an open-source, sub-millisecond vector and lexical search library & multi-tenancy server written in Rust. The SeekStorm client library can be embedded into your program, while the SeekStorm server is a standalone search server to be accessed via HTTP.

§Add required crates to your project

cargo add seekstorm_client_rs
cargo add tokio
cargo add serde_json

§use an asynchronous Rust runtime

use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {

// your SeekStorm code here

  Ok(())
}

§live

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let result=CLIENT.live(BASE_URL).await;

§create API key

use seekstorm_client_rs::{RestClient, ApikeyQuotaObject};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static MASTER_API_KEY: &str = "/iWStCpyfpd/BVlHOFtwnMgrFrmof4jGq/OQDWXQzcM=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let apikey_quota_object=ApikeyQuotaObject {
  indices_max: 10,
  indices_size_max: 100_000_000_000,
  documents_max: 100_000_000,
  operations_max: 1_000_000_000,
  rate_limit:None,
  demo: true,
  ..Default::default()
};

let result = CLIENT
  .create_apikey(BASE_URL, MASTER_API_KEY, &apikey_quota_object)
  .await;

§delete API key

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static MASTER_API_KEY: &str = "/iWStCpyfpd/BVlHOFtwnMgrFrmof4jGq/OQDWXQzcM=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let result = CLIENT
  .delete_apikey(BASE_URL, DEMO_API_KEY, MASTER_API_KEY)
  .await;

§get API key info

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let result = CLIENT
  .get_apikey_info(BASE_URL, DEMO_API_KEY)
  .await;

§create index

use seekstorm_client_rs::{RestClient, ApikeyQuotaObject, Clustering, CreateIndexRequest, DocumentCompression, FrequentwordType, LexicalSimilarity, NgramSet, StemmerType, StopwordType, TokenizerType, Inference};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let schema_json = r#"
  [{"field":"title","field_type":"Text","store":false,"index_lexical":false},
  {"field":"body","field_type":"Text","store":true,"index_lexical":true,"longest":true},
  {"field":"url","field_type":"Text","store":false,"index_lexical":false}]"#;
let schema = serde_json::from_str(schema_json).unwrap();

let create_index_request = CreateIndexRequest {
  index_name: "test_index".into(),
  similarity: LexicalSimilarity::Bm25f,
  tokenizer: TokenizerType::UnicodeAlphanumeric,
  stemmer: StemmerType::None,
  stop_words: StopwordType::None,
  frequent_words: FrequentwordType::English,
  synonyms: Vec::new(), //not supported in REST API?
  ngram_indexing: NgramSet::NgramFF as u8 | NgramSet::NgramFFF as u8,
  document_compression: DocumentCompression::Snappy,
  spelling_correction: None,
  query_completion: None,
  clustering: Clustering::None,
  inference: Inference::None,
  schema,
};
let result = CLIENT
  .create_index(BASE_URL, DEMO_API_KEY, &create_index_request)
 .await;

§get index info

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());
let index_id=0;

let result = CLIENT
  .get_index_info(BASE_URL, DEMO_API_KEY, index_id)
  .await;

§index document

use seekstorm_client_rs::{RestClient, Document};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let document_json = r#"
{"title":"title1 test","body":"body1","url":"url1"}"#;
let document=serde_json::from_str(document_json).unwrap();
let _result = CLIENT.index_document(BASE_URL, DEMO_API_KEY, 0,&document).await;

§index documents

use seekstorm_client_rs::{RestClient, Document};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let documents_json = r#"
[{"title":"title1 test","body":"body1","url":"url1"},
{"title":"title2","body":"body2 test","url":"url2"},
{"title":"title3 test","body":"body3 test","url":"url3"}]"#;
let documents_vec:Vec<Document>=serde_json::from_str(documents_json).unwrap();

CLIENT.index_documents(BASE_URL, DEMO_API_KEY, 0, &documents_vec).await;

§delete document by document id

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;
let doc_id=1;
CLIENT.delete_document_by_docid(BASE_URL, DEMO_API_KEY, index_id, doc_id).await;

§delete documents by document id

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let docid_vec=vec![1,2];
CLIENT.delete_documents_by_docid(BASE_URL, DEMO_API_KEY, 0, docid_vec).await;

§delete documents by query

use seekstorm_client_rs::{RestClient, ApikeyQuotaObject, Clustering, CreateIndexRequest, SearchRequestObject, DocumentCompression, FrequentwordType, LexicalSimilarity, NgramSet, StemmerType, StopwordType, TokenizerType, Inference, QueryRewriting, QueryType, ResultType, SearchMode};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let query = "test".into();

let search_request_object = SearchRequestObject {
  query_string: query,
  query_vector: None,
  enable_empty_query: false,
  offset: 0,
  length: 10,
  result_type: ResultType::TopkCount,
  query_type_default: QueryType::Intersection,
  search_mode: SearchMode::Lexical,
  realtime: false,
  query_rewriting: QueryRewriting::SearchOnly,
  highlights: Vec::new(),
  fields: Vec::new(),
  field_filter: Vec::new(),
  facet_filter: Vec::new(),
  distance_fields: Vec::new(),
  query_facets: Vec::new(),
  result_sort: Vec::new(),
};

CLIENT.delete_documents_by_query(BASE_URL, DEMO_API_KEY, 0, &search_request_object).await;

§update document

use seekstorm_client_rs::{RestClient, Document};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let id_document_json = r#"
[2,{"title":"title3 test","body":"body3 test","url":"url3"}]"#;
let id_document=serde_json::from_str(id_document_json).unwrap();
CLIENT.update_document(BASE_URL, DEMO_API_KEY, 0, id_document).await;

// ### commit index
let result = CLIENT.commit_index(BASE_URL, DEMO_API_KEY, 0).await;

§update documents

use seekstorm_client_rs::{RestClient, Document};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let id_document_vec_json = r#"
[[1,{"title":"title1 test","body":"body1","url":"url1"}],
[2,{"title":"title3 test","body":"body3 test","url":"url3"}]]"#;
let id_document_vec=serde_json::from_str(id_document_vec_json).unwrap();
CLIENT.update_documents(BASE_URL, DEMO_API_KEY, 0, id_document_vec).await;

// ### commit index
let result = CLIENT.commit_index(BASE_URL, DEMO_API_KEY, 0).await;

§query index

use seekstorm_client_rs::{RestClient,ApikeyQuotaObject, Clustering, CreateIndexRequest, SearchRequestObject, DocumentCompression, FrequentwordType, LexicalSimilarity, NgramSet, StemmerType, StopwordType, TokenizerType, Inference, QueryRewriting, QueryType, ResultType, SearchMode};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let query = "test".into();

let search_request_object = SearchRequestObject {
  query_string: query,
  query_vector: None,
  enable_empty_query: false,
  offset: 0,
  length: 10,
  result_type: ResultType::TopkCount,
  query_type_default: QueryType::Intersection,
  search_mode: SearchMode::Lexical,
  realtime: false,
  query_rewriting: QueryRewriting::SearchOnly,
  highlights: Vec::new(),
  fields: Vec::new(),
  field_filter: Vec::new(),
  facet_filter: Vec::new(),
  distance_fields: Vec::new(),
  query_facets: Vec::new(),
  result_sort: Vec::new(),
};
let result_object = CLIENT.query_index(BASE_URL, DEMO_API_KEY, 0,search_request_object).await;

// ### display results
for result in result_object.as_ref().unwrap().results.iter() {
  println!("result {:?} rank {:?} body field {:?}" , result.get("_id"),result.get("_score"), result.get("body"));
}
println!("result counts {} {} {}",result_object.as_ref().unwrap().results.len(), result_object.as_ref().unwrap().count, result_object.as_ref().unwrap().count_total);

§get document

use seekstorm_client_rs::{RestClient,GetDocumentRequest,Highlight};
use std::sync::LazyLock;
use std::collections::HashSet;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;
let doc_id=0;
let highlights:Vec<Highlight>= vec![
    Highlight {
        field: "body".to_string(),
        name:String::new(),
        fragment_number: 2,
        fragment_size: 160,
        highlight_markup: true,
        ..Default::default()
        },
    ];    

     let get_document_request = GetDocumentRequest {
        query_terms: Vec::new(),
        highlights: highlights,
        fields: Vec::new(),
        distance_fields: Vec::new(),
    };
    let doc=CLIENT.get_document(BASE_URL, DEMO_API_KEY, index_id,doc_id,&get_document_request).await.unwrap();

§document iterator

use seekstorm_client_rs::{RestClient, GetIteratorRequest};
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;

let get_iterator_request = GetIteratorRequest {
  document_id: Some(0),
  skip: 0,
  take: 1,
  include_deleted: false,
  include_document: true,
  fields: Vec::new(),
};
let result=CLIENT.document_iterator(BASE_URL, DEMO_API_KEY, index_id,get_iterator_request).await;

§index PDF file bytes

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;
use std::fs;
use std::path::Path;
use chrono::Utc;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;
let file_path=Path::new("C:/test.pdf");
let file_date=Utc::now().timestamp();
let document = fs::read(file_path).unwrap();
let result=CLIENT.index_pdf(BASE_URL, DEMO_API_KEY, index_id, file_path, file_date, document).await;

§get PDF file bytes

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;
let doc_id=0;

let result=CLIENT.get_pdf(BASE_URL, DEMO_API_KEY, index_id, doc_id).await;

§clear index

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;

let result=CLIENT.clear_index(BASE_URL, DEMO_API_KEY, index_id).await;

§delete index

use seekstorm_client_rs::RestClient;
use std::sync::LazyLock;

pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static DEMO_API_KEY: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
pub static CLIENT: LazyLock<RestClient> = LazyLock::new(|| RestClient::new());

let index_id=0;

let result=CLIENT.delete_index(BASE_URL, DEMO_API_KEY, index_id).await;

Re-exports§

pub use crate::api_endpoints::RestClient;

Modules§

api_endpoints
The api_endpoints module contains the implementation of the REST API client for SeekStorm.
index
Operate the index: reate_index, open_index, clear_index, close_index, delete_index, index_document(s)

Structs§

ApikeyQuotaObject
Quota per API key
CreateIndexRequest
Create index request object
GetDocumentRequest
Specifies which document and which field to return
GetIteratorRequest
Specifies which document ID to return
Highlight
Specifies the number and size of fragments (snippets, summaries) to generate from each specified field to provide a “keyword in context” (KWIC) functionality. With highlight_markup the matching query terms within the fragments can be highlighted with HTML markup.
IteratorResult
Iterator
IteratorResultItem
Iterator result
SearchRequestObject
Search request object
SearchResultObject
Search result object

Enums§

Clustering
Clustering defines the clustering behavior for approximate nearest neighbor (ANN) search: None, Auto, Fixed(usize).
DocumentCompression
Compression type for document store
FrequentwordType
FrequentwordType defines the frequentword behavior: None, English, German, French, Spanish, Custom. Adjacent frequent terms are combined to bi-grams, both in index and query: for shorter posting lists and faster phrase queries (only for bi-grams of frequent terms). The lists of stop_words and frequent_words should not overlap.
Inference
Inference type, to transform input text into vector embeddings.
This can be a predefined model2vec model, a custom model2vec model, an external inference, or no inference.
LexicalSimilarity
Similarity type defines the scoring and ranking of the search results:
NgramSet
N-gram indexing: n-grams are indexed in addition to single terms, for faster phrase search, at the cost of higher index size Setting valid both for index time and query time. Any change requires reindexing. bitwise OR flags:
QueryRewriting
Specifies whether query rewriting is enabled or disabled
QueryType
Specifies the default QueryType: The following query types are supported:
ResultType
The following result types are supported:
SearchMode
Specifies the default QueryMode: The following query modes are supported:
StemmerType
Defines stemming behavior, reducing inflected words to their word stem, base or root form. Stemming increases recall, but decreases precision. It can introduce false positive results.
StopwordType
StopwordType defines the stopword behavior: None, English, German, French, Spanish, Custom. Stopwords are removed, both from index and query: for compact index size and faster queries. Stopword removal has drawbacks: “The Who”, “Take That”, “Let it be”, “To be or not to be”, “The The”, “End of days”, “What might have been” are all valid queries for bands, songs, movies, literature, but become impossible when stopwords are removed. The lists of stop_words and frequent_words should not overlap.
TokenizerType
Defines tokenizer behavior: AsciiAlphabetic

Type Aliases§

Document
A document is a flattened, single level of key-value pairs, where key is an arbitrary string, and value represents any valid JSON value.