diff --git a/CHANGELOG.md b/CHANGELOG.md index 29050684..c8a507e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added - Added InfoResponse structure ([#187](https://github.com/opensearch-project/opensearch-rs/pull/187)) +- Added documentation on how to make raw json requests ([#196](https://github.com/opensearch-project/opensearch-rs/pull/196)) ### Dependencies - Bumps `sysinfo` from 0.28.0 to 0.29.0 - Bumps `serde_with` from ~2 to ~3 diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 8d44b9db..bc7d6199 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -7,6 +7,7 @@ - [Add a Document to the Index](#add-a-document-to-the-index) - [Search for a Document](#search-for-a-document) - [Delete the Index](#delete-the-index) + - [Make Raw Json Requests](#make-raw-json-requests) - [Amazon OpenSearch and OpenSearch Serverless](#amazon-opensearch-and-opensearch-serverless) - [Create a Client](#create-a-client-1) @@ -108,6 +109,94 @@ client .await?; ``` +### Make Raw Json Requests + +To invoke an API that is not supported by the client, use the `client.send` method to do so. See [examples/json](./opensearch/examples/json.rs) for a complete working example. + +#### GET +The following example returns the server version information via `GET /`. +```rust +let info: Value = client + .send::<(), ()>( + Method::Get, + "/", + HeaderMap::new(), + None, + None, + None, + ) + .await? + .json() + .await?; + +println!("Welcome to {} {}" , info["version"]["distribution"] , info["version"]["number"]); + +``` +#### PUT +The following example creates an index. + +```rust +let index_body: JsonBody<_> = json!({ + "settings": { + "index": { + "number_of_shards" : 4 + } + } + }).into(); + +client + .send( + Method::Put, + "/movies", + HeaderMap::new(), + Option::<&()>::None, + Some(index_body), + None, + ) + .await?; +``` +#### POST +The following example searches for a document. + +```rust +let q = "miller"; + +let query: JsonBody<_> = json!({ + "size": 5, + "query": { + "multi_match": { + "query": q, + "fields": ["title^2", "director"] + } + } +}).into(); +client + .send( + Method::Post, + "/movies/_search", + HeaderMap::new(), + Option::<&()>::None, + Some(query), + None, + ) + .await?; +``` + +#### DELETE +The following example deletes an index. +```rust +client + .send::<(), ()>( + Method::Delete, + "/movies", + HeaderMap::new(), + None, + None, + None, + ) + .await?; +``` + ## Amazon OpenSearch and OpenSearch Serverless This library supports [Amazon OpenSearch Service](https://aws.amazon.com/opensearch-service/) and [OpenSearch Serverless](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless.html). diff --git a/opensearch/examples/json.rs b/opensearch/examples/json.rs new file mode 100644 index 00000000..2b3395f2 --- /dev/null +++ b/opensearch/examples/json.rs @@ -0,0 +1,139 @@ +use serde_json::{json, Value}; + +use opensearch::auth::Credentials; +use opensearch::cert::CertificateValidation; +use opensearch::http::headers::HeaderMap; +use opensearch::http::transport::{SingleNodeConnectionPool, TransportBuilder}; +use opensearch::http::{Method, Url}; +use opensearch::http::request::JsonBody; +use opensearch::OpenSearch; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let url = Url::parse("https://localhost:9200")?; + let credentials = Credentials::Basic("admin".into(), "admin".into()); + let transport = TransportBuilder::new(SingleNodeConnectionPool::new(url)) + .cert_validation(CertificateValidation::None) + .auth(credentials) + .build()?; + let client = OpenSearch::new(transport); + + let index_name = "movies"; + let document_id = "1"; + + let info: Value = client + .send::<(), ()>( + Method::Get, + "/", + HeaderMap::new(), + None, + None, + None, + ) + .await? + .json() + .await?; + + println!( + "Welcome to {} {}", + info["version"]["distribution"], info["version"]["number"] + ); + + // Create an index + let index_body : JsonBody<_> = json!({ + "settings": { + "index": { + "number_of_shards" : 4 + } + } + }).into(); + + let create_index_response = client + .send( + Method::Put, + &format!("/{index_name}"), + HeaderMap::new(), + Option::<&()>::None, + Some(index_body), + None, + ) + .await?; + + assert_eq!(create_index_response.status_code(), 200); + + // add a document to the index + let document: JsonBody<_> = json!({ + "title": "Moneyball", + "director": "Bennett Miller", + "year": "2011" + }).into(); + let create_document_response = client + .send( + Method::Put, + &format!("/{index_name}/_doc/{document_id}"), + HeaderMap::new(), + Some(&[("refresh", "true")]), + Some(document), + None, + ) + .await?; + + assert_eq!(create_document_response.status_code(), 201); + + // Search for a document + let q = "miller"; + let query : JsonBody<_> = json!({ + "size": 5, + "query": { + "multi_match": { + "query": q, + "fields": ["title^2", "director"] + } + } + }).into(); + + let search_response = client + .send( + Method::Post, + &format!("/{index_name}/_search"), + HeaderMap::new(), + Option::<&()>::None, + Some(query), + None, + ) + .await?; + + assert_eq!(search_response.status_code(), 200); + let search_result = search_response.json::().await?; + println!("Hits: {:#?}", search_result["hits"]["hits"].as_array().unwrap()); + + // Delete the document + let delete_document_response = client + .send::<(),()>( + Method::Delete, + &format!("/{index_name}/_doc/{document_id}"), + HeaderMap::new(), + None, + None, + None, + ) + .await?; + + assert_eq!(delete_document_response.status_code(), 200); + + // Delete the index + let delete_response = client + .send::<(),()>( + Method::Delete, + &format!("/{index_name}"), + HeaderMap::new(), + None, + None, + None, + ) + .await?; + + assert_eq!(delete_response.status_code(), 200); + + Ok(()) +}