diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f588db0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing guide + +## Local development + +### Prerequisites + +- Install [homebrew](https://brew.sh/) if you haven't already +- Install `brew install just`. just is a command line tool used to run commands defined inside the project `justfile`. You run commands by passing the command name, for example `just build-openapi`. + +### Clone the repository + +This repository relies on a git submodule to get access to our openapi spec. To clone the repository, use the command: + +``` +git clone --recurse-submodules git@github.com:pinecone-io/pinecone-rust-client.git +``` + +Or, if you have already cloned the repository, you can update the submodules with + +``` +git submodule update --init --recursive +``` + +### Generating code from OpenAPI and Proto specs + +The generated code is already checked into the repository and normally should not need to be modified. + +To regenerate OpenAPI or Protobuf code, you will require access to the private `apis` repository. +- Follow setup instructions for the `apis` repository: [apis setup](https://github.com/pinecone-io/apis) + +OpenAPI + +- You need [Docker Desktop](https://www.docker.com/products/docker-desktop/) in order to generate code using openapi. Look at `codegen/build-oas.sh` to see how this is used. + - Make sure Docker is running. +- `just build-openapi` + - References the spec files from the `codegen/apis` submodule + - Outputs the generated code to `src/openapi` + +Protobuf +- `brew install protobuf` +- `cargo install protobuf-codegen` and add it to path: `PATH="$HOME/.cargo/bin:$PATH"` +- `just build-proto` + - References the spec files from the `codegen/apis` submodule + - Outputs the generated code to `src/protos` + +Alternatively, you can run `just build-client` to regenerate both OpenAPI and Protobuf code. + +What the build process looks like in all cases: +- Build the `apis` submodule to produce consolidated .yaml files in `codegen/apis/_build` +- Create a `version.rs` file containing API version info based on the defined value in the justfile +- Run build scripts for OpenAPI and/or Protobuf, propagating the API version + +### Build and run + +Build and run the project: +- `cargo build` builds the project +- `cargo test` builds the project and runs tests diff --git a/Cargo.lock b/Cargo.lock index 4905286..9218c41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -628,6 +628,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -635,6 +650,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -643,6 +659,17 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -706,9 +733,13 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1455,6 +1486,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "serial_test", "snafu", "temp-env", "tokio", @@ -1864,6 +1896,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ccfb12511cdb770157ace92d7dda771e498445b78f9886e8cdbc5140a4eced" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.23" @@ -1879,6 +1920,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdd" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177258b64c0faaa9ffd3c65cd3262c2bc7e2588dbbd9c1641d0346145c1bbda8" + [[package]] name = "security-framework" version = "2.11.1" @@ -1955,6 +2002,31 @@ dependencies = [ "serde", ] +[[package]] +name = "serial_test" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.71", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" diff --git a/Cargo.toml b/Cargo.toml index 04d2946..71d75c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,21 +2,25 @@ name = "pinecone-sdk" version = "0.1.0" edition = "2021" +description = "Pinecone Rust SDK" +repository = "https://github.com/pinecone-io/pinecone-rust-client" +rust-version = "1.78.0" +readme = "./README.md" license = "Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] tokio = { version = "1", features = ["full"] } -regex = "1.10.4" -serde_json = "1.0.117" -snafu = "0.8.3" -rand = "0.8.5" -tonic = { version = "0.11.0", features = ["tls", "transport", "tls-roots"] } -prost = "0.12.6" -prost-types = "0.12.6" -# reqwest = "0.12.5" -once_cell = "1.19.0" +regex = "1.10" +serde_json = "1.0" +snafu = "0.8" +rand = "0.8" +tonic = { version = "0.11", features = ["tls", "transport", "tls-roots"] } +prost = "0.12" +prost-types = "0.12" +# reqwest = "0.12" +once_cell = "1.19" # openapi serde = { version = "^1.0", features = ["derive"] } @@ -26,8 +30,9 @@ uuid = { version = "^1.8", features = ["serde", "v4"] } reqwest = { version = "^0.12", features = ["json", "multipart"] } [dev-dependencies] -temp-env = "0.3.6" +temp-env = "0.3" httpmock = "0.7.0-rc.1" +serial_test = "3.1" [build-dependencies] -tonic-build = "0.11.0" +tonic-build = "0.11" diff --git a/README.md b/README.md index aeabd9a..9095932 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,382 @@ # Pinecone Rust SDK -- [Asana backlog](https://app.asana.com/0/1207449888227387/1207449824366220) +## Documentation -# Prerequisites +[reference the documentation here] -- You need [Docker Desktop](https://www.docker.com/products/docker-desktop/) in order to generate code using openapi. Look at `codegen/build-oas.sh` to see how this is used. -- Install [homebrew](https://brew.sh/) if you haven't already -- Install `brew install just`. just is a command line tool used to run commands defined inside the project `justfile`. You run commands by passing the command name, for example `just build-openapi`. +### Example code -Dependencies for generating code from OpenAPI and protobuf specifications: -- Follow setup instructions for the `apis` repository -- `brew install protobuf` -- `cargo install protobuf-codegen` and add it to path: `PATH="$HOME/.cargo/bin:$PATH"` +[reference the sample app] -# Clone the repository +## Prerequisites -This repository relies on a git submodule to get access to our openapi spec. To clone the repository, use the command: +Rust version? +Before you can use the Pinecone SDK, you must sign up for an account and find your API key in the Pinecone console dashboard at [https://app.pinecone.io](https://app.pinecone.io). + +## Installation + +How to install - instruction for getting the package from crates.io + +## Usage + +The `PineconeClient` class is the main point of entry into the Rust SDK. To instantiate it, call `Pinecone::new(...)`, which takes in an API key, control plane host, additional headers, and a source tag. All are optional arguments, however not all are truly optional: +- The API key must be passed in either as an argument or as an environment variable called `PINECONE_API_KEY`. If not passed in as an argument, the client will attempt to read in an environment variable value. +- The control plane host, if not passed in as an argument, will attempt to read in an environment variable called `PINECONE_CONTROLLER_HOST`. If it is not an environment variable, it will default to `https://api.pinecone.io`. + +# Indexes + +## Create Index + +### Create serverless index +The following example creates a serverless index in the `us-east-1` region of AWS. For more information on serverless and regional availability, see [Understanding indexes](https://docs.pinecone.io/guides/indexes/understanding-indexes#serverless-indexes) +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::{Metric, Cloud, WaitPolicy, IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.create_serverless_index( + "index-name", // Name of the index + 10, // Dimension of the vectors + Metric::Cosine, // Distance metric + Cloud::Aws, // Cloud provider + "us-east-1", // Region + WaitPolicy::NoWait // Timeout +).await?; +``` + +### Create pod index +The following example creates a pod index in the `us-east-1` region of AWS. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::{Metric, Cloud, WaitPolicy, IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.create_pod_index( + "index-name", // Index name + 10, // Dimension + Metric::Cosine, // Distance metric + "us-east-1", // Region + "p1.x1", // Pod type + 1, // Number of pods + None, // Number of replicas + None, // Number of shards + None, // Metadata to index + None, // Source collection + WaitPolicy::NoWait // Wait policy +).await?; +``` + +Pod indexes support several optional configuration fields. The following example constructs a pod index with some specification for these fields. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::{Metric, Cloud, WaitPolicy, IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.create_pod_index( + "index-name", // Index name + 10, // Dimension + Metric::Cosine, // Distance metric + "us-east-1", // Region + "p1.x1", // Pod type + 1, // Number of pods + Some(1), // Number of replicas + Some(1), // Number of shards + Some( // Metadata fields to index + &vec!["genre", + "title", + "imdb_rating"]), + Some("collection"), // Source collection + WaitPolicy::NoWait // Wait policy +).await?; +``` + +## List indexes +The following example lists all indexes in your project. +```rust +use pinecone_sdk::pinecone::{ClientClient, control::IndexList}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_list: IndexList = pinecone.list_indexes().await?; +``` + +## Describe index +The following example returns information about the index `index-name`. +```rust +use pinecone_sdk::pinecone::{PineconeClient, control::IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.describe_index("index-name").await?; +``` + +## Configure index +Configuring an index takes in three optional parameters -- a DeletionProtection enum, the number of replicas, and the pod type. The deletion protection can be updated for any index type, while the number of replicas and the pod type can only be updated for pod indexes. + +The following example disables deletion protection for the index `index-name`. +```rust +use pinecone_sdk::pinecone::{PineconeClient, control::IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.configure_index("index-name", Some(DeletionProtection::Disabled), None, None).await?; +``` + +The following example changes the index `index-name` to have 6 replicas and pod type `s1`. The deletion protection type will not be changed in this case. +```rust +use pinecone_sdk::pinecone::{PineconeClient, control::IndexModel}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let index_description: IndexModel = pinecone.configure_index("index-name", None, Some(6), Some("s1")).await?; +``` + +## Delete index +The following example deletes the index `index-name`. +```rust +use pinecone_sdk::pinecone::PineconeClient; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +pinecone.delete_index("index-name").await?; +``` + +## Describe index statistics +The following example returns statistics about the index with host `index-host`. +Without filter +```rust +use std::collections::BTreeMap; +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::DescribeIndexStatsResponse; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let response: DescribeIndexStatsResponse = index.describe_index_stats(None).await?; ``` -git clone --recurse-submodules git@github.com:pinecone-io/pinecone-rust-client.git + +With filter +```rust +use std::collections::BTreeMap; +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Value, Kind, Metadata, DescribeIndexStatsResponse}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let mut fields = BTreeMap::new(); +let kind = Some(Kind::StringValue("value".to_string())); +fields.insert("field".to_string(), Value { kind }); + +let response: DescribeIndexStatsResponse = index.describe_index_stats(Some(Metadata { fields })).await?; ``` -Or, if you have already cloned the repository, you can update the submodules with +## Upsert vectors +The following example upserts two vectors into the index with host `index-host`. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Vector, UpsertResponse}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; +let mut index = pinecone.index("index-host").await?; + +let vectors = [Vector { + id: "id1".to_string(), + values: vec![1.0, 2.0, 3.0, 4.0], + sparse_values: None, + metadata: None, +}, Vector { + id: "id2".to_string(), + values: vec1![2.0, 3.0, 4.0, 5.0], + sparse_values: None, + metadata: None, +}]; + +let response: UpsertResponse = index.upsert(&vectors, &"namespace".into()).await?; ``` -git submodule update --init --recursive + +## Query vectors +There are two supported ways of querying an index. +### Query by index +The following example queries the index with host `index-host` for the vector with ID `vector-id`, and returns the top 10 matches. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Namespace, QueryResponse}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +// Connect to index at host "index-host" +let mut index = pinecone.index("index-host").await?; + +// Query the vector with id "vector-id" in the namespace "namespace" +let response: QueryResponse = index.query_by_id( + "vector-id".to_string(), + 10, + &Namespace::default(), + None, + None, + None +).await?; ``` -# Build and run +### Query by value +The following example queries the index with host `index-host` for the vector with values `[1.0, 2.0, 3.0, 4.0]`, and returns the top 10 matches. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Namespace, QueryResponse}; -OpenAPI -- The generated code is comitted to the repository, but to regenerate run `just build-openapi` -- References the spec files from the `codegen/apis` submodule -- Outputs the generated code to `openapi` +let pinecone = PineconeClient::new('<>', None, None, None)?; -Protobuf -- Code is generated from protobuf during the project build process (`cargo build`) using the build script `build.rs` -- The generated code is outputted to `/target/debug/build/pinecone_sdk-{hash}/out` +let mut index = pinecone.index("index-host").await?; + +let vector = vec![1.0, 2.0, 3.0, 4.0]; + +let response: QueryResponse = index.query_by_value( + vector, + None, + 10, + &Namespace::default(), + None, + None, + None +).await?; +``` + +## Delete vectors +There are three supported ways of deleting vectors. +### Delete by ID +The following example deletes the vector with ID `vector-id` in the namespace `namespace`. +```rust +use pinecone_sdk::pinecone::PineconeClient; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let ids = ["vector-id"] + +index.delete_by_id(&ids, &"namespace".into()).await?; +``` + +### Delete by filter: +The following example deletes vectors that satisfy the filter in the namespace `namespace`. +```rust +use std::collections::BTreeMap; +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Metadata, Value, Kind, Namespace}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut fields = BTreeMap::new(); +let kind = Some(Kind::StringValue("value".to_string())); +fields.insert("field".to_string(), Value { kind }); + +index.delete_by_filter(Metadata { fields }, &"namespace".into()).await?; +``` + +### Delete all: +The following example deletes all vectors in the namespace `namespace`. +```rust +use pinecone_sdk::pinecone::PineconeClient; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +index.delete_all(&"namespace".into()).await?; +``` + +## Fetch vectors +The following example fetches the vectors with IDs `1` and `2` from the default namespace. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::FetchResponse; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let vectors = &["1".to_string(), "2".to_string()]; + +let response: FetchResponse = index.fetch(vectors, &Default::default()).await?; +``` + +## Update vectors +The following example updates the vector with ID `vector-id` in the namespace `namespace` to have values `[1.0, 2.0, 3.0, 4.0]`. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::UpdateResponse; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let response: UpdateResponse = index.update("vector-id", vec![1.0, 2.0, 3.0, 4.0], None, None, &"namespace".into()).await?; +``` + +## List vectors +The following example lists vectors in the namespace `namespace`. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::data::{Namespace, ListResponse}; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let mut index = pinecone.index("index-host").await?; + +let response: ListResponse = index.list(&"namespace".into(), None, None, None).await?; +``` + +# Collections +## Create collection +The following example creates a collection `collection-name` in the index `index-name`. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::CollectionModel; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let collection: CollectionModel = pinecone.create_collection("collection-name", "index-name").await?; +``` + +## List collections +The following example lists all collections in a project. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::CollectionList; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let collection_list: CollectionList = pinecone.list_collections().await?; +``` + +## Describe collection +The following example describes the collection `collection-name`. +```rust +use pinecone_sdk::pinecone::PineconeClient; +use pinecone_sdk::pinecone::control::CollectionModel; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +let collection: CollectionModel = pinecone.describe_collection("collection-name").await?; +``` + +## Delete collection +The following example deletes the collection `collection-name`. +```rust +use pinecone_sdk::pinecone::PineconeClient; + +let pinecone = PineconeClient::new('<>', None, None, None)?; + +pinecone.delete_collection("collection-name").await?; +``` -Build and run the project: -- `cargo build` builds the project -- `cargo test` builds the project and runs tests +# Contributing +If you'd like to make a contribution, or get setup locally to develop the Pinecone Rust client, please see our [contributing guide](https://github.com/pinecone-io/pinecone-rust-client/blob/emily/update-readme/CONTRIBUTING.md) \ No newline at end of file diff --git a/src/pinecone/control.rs b/src/pinecone/control.rs index fe68da4..6eb5555 100644 --- a/src/pinecone/control.rs +++ b/src/pinecone/control.rs @@ -35,7 +35,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Create an index. /// let response: Result = pinecone.create_serverless_index( @@ -118,14 +118,14 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError> { - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Create a pod index. /// let response: Result = pinecone.create_pod_index( /// "index_name", // Name of the index /// 10, // Dimension of the index /// Metric::Cosine, // Distance metric - /// "us-east-1-aws", // Environment + /// "us-east-1", // Environment /// "p1.x1", // Pod type /// 1, // Number of pods /// 1, // Number of replicas @@ -260,7 +260,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Describe an index in the project. /// let response: Result = pinecone.describe_index("index-name").await; @@ -292,7 +292,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // List all indexes in the project. /// let response: Result = pinecone.list_indexes().await; @@ -330,7 +330,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Configure an index in the project. /// let response: Result = pinecone.configure_index( @@ -409,7 +409,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Delete an index in the project. /// let response: Result<(), PineconeError> = pinecone.delete_index("index-name").await; @@ -442,7 +442,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Describe an index in the project. /// let response: Result = pinecone.create_collection("collection-name", "index-name").await; @@ -479,14 +479,15 @@ impl PineconeClient { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; + /// use pinecone_sdk::models::CollectionModel; /// use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Describe a collection in the project. - /// let response = pinecone.describe_collection("collection-name").await; + /// let collection: CollectionModel = pinecone.describe_collection("collection-name").await?; /// # Ok(()) /// # } /// ``` @@ -513,7 +514,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // List all collections in the project. /// let response: Result = pinecone.list_collections().await; @@ -544,7 +545,7 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// /// // Delete a collection in the project. /// let response: Result<(), PineconeError> = pinecone.delete_collection("collection-name").await; diff --git a/src/pinecone/data.rs b/src/pinecone/data.rs index 43765a3..0d5cbd9 100644 --- a/src/pinecone/data.rs +++ b/src/pinecone/data.rs @@ -74,15 +74,14 @@ impl Index { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::{Namespace, Vector}; + /// use pinecone_sdk::pinecone::data::{Vector, UpsertResponse}; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// let vectors = [Vector { /// id: "vector-id".to_string(), @@ -92,7 +91,7 @@ impl Index { /// }]; /// /// // Upsert vectors into the namespace "namespace" in the index - /// let response = index.upsert(&vectors, &"namespace".into()).await.unwrap(); + /// let response: UpsertResponse = index.upsert(&vectors, &"namespace".into()).await?; /// # Ok(()) /// # } /// ``` @@ -130,18 +129,17 @@ impl Index { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::Namespace; + /// use pinecone_sdk::pinecone::data::ListResponse; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// // List all vectors in the namespace "namespace" - /// let response = index.list(&"namespace".into(), None, None, None).await.unwrap(); + /// let response: ListResponse = index.list(&"namespace".into(), None, None, None).await?; /// # Ok(()) /// # } /// ``` @@ -181,22 +179,22 @@ impl Index { /// ```no_run /// use std::collections::BTreeMap; /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::{Value, Kind, Metadata, Namespace}; + /// use pinecone_sdk::pinecone::data::{Value, Kind, Metadata, DescribeIndexStatsResponse}; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// // Construct a metadata filter /// let mut fields = BTreeMap::new(); - /// fields.insert("field".to_string(), Value { kind: Some(Kind::StringValue("value".to_string())) }); + /// let kind = Some(Kind::StringValue("value".to_string())); + /// fields.insert("field".to_string(), Value { kind }); /// /// // Describe the index statistics - /// let response = index.describe_index_stats(Some(Metadata { fields })).await.unwrap(); + /// let response: DescribeIndexStatsResponse = index.describe_index_stats(Some(Metadata { fields })).await?; /// # Ok(()) /// # } /// ``` @@ -247,18 +245,23 @@ impl Index { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::{Namespace, SparseValues, Metadata}; + /// use pinecone_sdk::pinecone::data::UpdateResponse; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// // Update the vector with id "vector-id" in the namespace "namespace" - /// let response = index.update("vector-id", vec![1.0, 2.0, 3.0, 4.0], None, None, &"namespace".into()).await.unwrap(); + /// let response: UpdateResponse = index.update( + /// "vector-id", + /// vec![1.0, 2.0, 3.0, 4.0], + /// None, + /// None, + /// &"namespace".into() + /// ).await?; /// # Ok(()) /// # } /// ``` @@ -304,18 +307,24 @@ impl Index { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::Namespace; + /// use pinecone_sdk::pinecone::data::{Namespace, QueryResponse}; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); - /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); - /// - /// // Query the vector with id "vector-id" in the namespace "namespace" - /// let response = index.query_by_id("vector-id", 10, &Namespace::default(), None, None, None).await.unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; + /// + /// let mut index = pinecone.index("index-host").await?; + /// + /// // Query the vector with id "vector-id" in the default namespace + /// let response: QueryResponse = index.query_by_id( + /// "vector-id", + /// 10, + /// &Namespace::default(), + /// None, + /// None, + /// None + /// ).await?; /// # Ok(()) /// # } /// ``` @@ -360,20 +369,27 @@ impl Index { /// ### Example /// ```no_run /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::Namespace; + /// use pinecone_sdk::pinecone::data::{Namespace, QueryResponse}; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// let vector = vec![1.0, 2.0, 3.0, 4.0]; /// /// // Query the vector in the default namespace - /// let response = index.query_by_value(vector, None, 10, &Namespace::default(), None, None, None).await.unwrap(); + /// let response: QueryResponse = index.query_by_value( + /// vector, + /// None, + /// 10, + /// &Namespace::default(), + /// None, + /// None, + /// None + /// ).await?; /// # Ok(()) /// # } /// ``` @@ -419,15 +435,14 @@ impl Index { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// let ids = ["vector-id"]; /// /// // Delete vectors from the namespace "namespace" that have the ids in the list - /// let response = index.delete_by_id(&ids, &"namespace".into()).await.unwrap(); + /// index.delete_by_id(&ids, &"namespace".into()).await?; /// # Ok(()) /// # } /// ``` @@ -463,13 +478,12 @@ impl Index { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// // Delete all vectors from the namespace "namespace" - /// let response = index.delete_all(&"namespace".into()).await.unwrap(); + /// index.delete_all(&"namespace".into()).await?; /// # Ok(()) /// # } /// ``` @@ -502,17 +516,17 @@ impl Index { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// // Construct a metadata filter /// let mut fields = BTreeMap::new(); - /// fields.insert("field".to_string(), Value { kind: Some(Kind::StringValue("value".to_string())) }); + /// let kind = Some(Kind::StringValue("value".to_string())); + /// fields.insert("field".to_string(), Value { kind }); /// /// // Delete vectors from the namespace "namespace" that satisfy the filter - /// let response = index.delete_by_filter(Metadata { fields }, &"namespace".into()).await.unwrap(); + /// index.delete_by_filter(Metadata { fields }, &"namespace".into()).await?; /// # Ok(()) /// # } /// ``` @@ -555,20 +569,19 @@ impl Index { /// ```no_run /// use std::collections::BTreeMap; /// use pinecone_sdk::pinecone::PineconeClient; - /// use pinecone_sdk::pinecone::data::{Metadata, Value, Kind}; + /// use pinecone_sdk::pinecone::data::FetchResponse; /// # use pinecone_sdk::utils::errors::PineconeError; /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url - /// let mut index = pinecone.index("index-host").await.unwrap(); + /// let mut index = pinecone.index("index-host").await?; /// /// let vectors = &["1", "2"]; /// /// // Fetch vectors from the default namespace that have the ids in the list - /// let response = index.fetch(vectors, &Default::default()).await.unwrap(); + /// let response: FetchResponse = index.fetch(vectors, &Default::default()).await?; /// Ok(()) /// } /// ``` @@ -635,10 +648,9 @@ impl PineconeClient { /// /// # #[tokio::main] /// # async fn main() -> Result<(), PineconeError>{ - /// let pinecone = PineconeClient::new(None, None, None, None).unwrap(); + /// let pinecone = PineconeClient::new(None, None, None, None)?; /// - /// // Connect to index host url "index-host" - /// let index = pinecone.index("index-host").await.unwrap(); + /// let index = pinecone.index("index-host").await?; /// # Ok(()) /// # } /// ``` diff --git a/tests/integration_test_control.rs b/tests/integration_test_control.rs index d608ecf..eaedba4 100644 --- a/tests/integration_test_control.rs +++ b/tests/integration_test_control.rs @@ -7,6 +7,7 @@ use pinecone_sdk::pinecone::PineconeClient; use pinecone_sdk::utils::errors::PineconeError; use std::collections::HashMap; use std::time::Duration; +use serial_test::serial; mod common; @@ -253,6 +254,7 @@ async fn test_delete_index_err() -> Result<(), PineconeError> { } #[tokio::test] +#[serial] async fn test_configure_index() -> Result<(), PineconeError> { let pinecone = PineconeClient::new(None, None, None, None).expect("Failed to create Pinecone instance"); @@ -396,6 +398,7 @@ async fn test_configure_invalid_index_err() -> Result<(), PineconeError> { } #[tokio::test] +#[serial] async fn test_create_delete_collection() -> Result<(), PineconeError> { let pinecone = PineconeClient::new(None, None, None, None).expect("Failed to create Pinecone instance"); diff --git a/tests/integration_test_data.rs b/tests/integration_test_data.rs index 334c926..598c34f 100644 --- a/tests/integration_test_data.rs +++ b/tests/integration_test_data.rs @@ -547,6 +547,7 @@ async fn test_fetch_vectors() -> Result<(), PineconeError> { .expect("Failed to fetch vectors"); assert_eq!(fetch_response.namespace, namespace.name); + assert_eq!(fetch_response.vectors.len(), 2); let vectors = fetch_response.vectors; assert_eq!( *vectors.get("1").unwrap(),