Skip to main content

Quickstart to On-Demand Search

Zilliz Cloud provides on-demand compute resources, allowing you to run similarity searches and queries on demand. As shown in the figure below, compute resources automatically suspend when no requests arrive, and suspended compute resources do not incur charges.

ZhWHbgOD0o56IpxbQ32ctGaInBe

Step 1: Connect to a project endpoint.​

Before working on a database, connect to the project endpoint. You can obtain the project endpoint on the quickstart page after enabling on-demand compute on the Zilliz Cloud console.

Notes
  • Managed collection operations require an API key for authentication. This flow does not support username:password authentication.

  • Managed collections in databases for on-demand compute do not require load operations.

python
from pymilvus import MilvusClient

# connect to database
client = MilvusClient(
# a project-specific on-demand compute endpoint
uri="https://{project-id}.{region}.api.zillizcloud.com",
token="YOUR_API_KEY"
)
rust
use milvus::v2::prelude::*;

// connect to database
let config = ConnectConfig::new()
.uri("https://{project-id}.{region}.api.zillizcloud.com")
.token("YOUR_API_KEY");
let client = ClientV2::new(&config).await?;
c++
#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();
milvus::ConnectParam connect_param(
"https://{project-id}.{region}.api.zillizcloud.com",
"YOUR_API_KEY"
);

auto status = client->Connect(connect_param);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

Step 2: (Optional) Create a database.​

Zilliz Cloud ships with a default database. If you choose that, skip this step. You can also create a database as follows.

python
client.create_database(
db_name="my_database"
)
rust
client
.create_database(
CreateDatabaseRequest::builder()
.database_name("my_database")
.build()?,
)
.await?;
c++
milvus::CreateDatabaseRequest request;
request.WithDatabaseName("my_database");

auto status = client->CreateDatabase(request);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

Step 3: Create a managed collection.​

Once the database is ready, you can create managed collections in it. Unlike an external collection that maps collection columns to external data files, a managed collection asks you to import data for significant performance gains.

The following example demonstrates how to set up the collection schema and create a collection.

python
from pymilvus import MilvusClient, DataType

schema = MilvusClient.create_schema()

schema.add_field(
field_name="product_id",
datatype=DataType.INT64,
is_primary=True
)

schema.add_field(
field_name="product_name",
datatype=DataType.VARCHAR,
max_length=512
)

schema.add_field(
field_name="embedding",
datatype=DataType.FLOAT_VECTOR,
dim=768
)
rust
let schema = CollectionSchema::new()
.add_field(
FieldSchema::new()
.name("product_id")
.data_type(DataType::Int64)
.primary_key(true),
)
.add_field(
FieldSchema::new()
.name("product_name")
.data_type(DataType::VarChar)
.max_length(512),
)
.add_field(
FieldSchema::new()
.name("embedding")
.data_type(DataType::FloatVector)
.dimension(768),
);
c++
auto schema = std::make_shared<milvus::CollectionSchema>();

schema->AddField(milvus::FieldSchema("product_id", milvus::DataType::INT64)
.WithPrimaryKey(true));
schema->AddField(milvus::FieldSchema("product_name", milvus::DataType::VARCHAR)
.WithMaxLength(512));
schema->AddField(milvus::FieldSchema("embedding", milvus::DataType::FLOAT_VECTOR)
.WithDimension(768));

Then you can create a collection with the above schema. If you decide to use the default database, you can safely skip the db_name parameter.

python
client.use_database(
db_name="my_database"
)

# create the collection
client.create_collection(
collection_name="prod_collection",
schema=schema
)
rust
client
.use_database("my_database")
.await?;

client
.create_collection(
CreateCollectionRequest::builder()
.collection_name("prod_collection")
.schema(schema)
.build()?,
)
.await?;
c++
auto status = client->UseDatabase("my_database");
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

milvus::CreateCollectionRequest request;
request.WithCollectionName("prod_collection")
.WithCollectionSchema(schema);

status = client->CreateCollection(request);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

Step 4: Create indexes.​

You need to create indexes for all vector fields and, optionally, for selected scalar fields.

python
index_params = client.prepare_index_params()

# Add indexes
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX",
metric_type="COSINE"
)

index_params.add_index(
field_name="product_name",
index_type="AUTOINDEX"
)

client.create_index(
db_name="my_database",
collection_name="prod_collection",
index_params=index_params
)
rust
client
.create_index(
CreateIndexRequest::builder()
.collection_name("prod_collection")
.index_params(vec![
IndexParam::new()
.field_name("embedding")
.index_type(IndexType::AutoIndex)
.metric_type(MetricType::Cosine),
IndexParam::new()
.field_name("product_name")
.index_type(IndexType::AutoIndex),
])
.build()?,
)
.await?;
c++
milvus::CreateIndexRequest request;
request.WithDatabaseName("my_database")
.WithCollectionName("prod_collection")
.AddIndex(milvus::IndexDesc(
"embedding",
"embedding",
milvus::IndexType::AUTOINDEX,
milvus::MetricType::COSINE))
.AddIndex(milvus::IndexDesc(
"product_name",
"product_name",
milvus::IndexType::AUTOINDEX));

auto status = client->CreateIndex(request);

Step 5: Import data.​

Once everything is set up, you can import the processed data. The following example assumes that you have stored the processed data in an external storage bucket.

For the data format in your bucket or storage integrations, refer to Format Options.

python
from pymilvus.bulk_writer import bulk_import

# The path should be relative to the root
# of a zilliz cloud volume or an external storage
OBJECT_URLS = [[
"https://s3.us-west-2.amazonaws.com/your-bucket/path/in/external/storage.json"
]]
ACCESS_KEY = "YOUR_STORAGE_ACCESS_KEY"
SECRET_KEY = "YOUR_STORAGE_SECRET_KEY"

res = bulk_import(
api_key="YOUR_ZILLIZ_API_KEY",
url="https://api.cloud.zilliz.com",
project_id="proj-xxxxxxxxxxxxxxxxxxx",
region_id="aws-us-west-2",
db_name="my_database",
collection_name="prod_collection",
object_urls=OBJECT_URLS,
access_key=ACCESS_KEY,
secret_key=SECRET_KEY
)

# job-xxxxxxxxxxxxxxxxxxxxx
rust
use milvus::v2::bulk_import::{BulkImport, BulkImportConfig, BulkImportRequest};

let import_client = BulkImport::new(
&BulkImportConfig::new()
.url("https://api.cloud.zilliz.com")
.api_key("YOUR_ZILLIZ_API_KEY"),
)?;

let request = BulkImportRequest::builder()
.database_name("my_database")
.collection_name("prod_collection")
.project_id("proj-xxxxxxxxxxxxxxxxxxx")
.region_id("aws-us-west-2")
.object_url("https://s3.us-west-2.amazonaws.com/your-bucket/path/in/external/storage.json")
.access_key("YOUR_STORAGE_ACCESS_KEY")
.secret_key("YOUR_STORAGE_SECRET_KEY")
.build()?;

let resp = import_client.bulk_import(request).await?;
// job-xxxxxxxxxxxxxxxxxxxxx
c++
#include "milvus/BulkImport.h"

nlohmann::json res = milvus::BulkImport::CreateImportJobs(
"https://api.cloud.zilliz.com", // url
"prod_collection", // collection_name
{"https://s3.us-west-2.amazonaws.com/your-bucket/path/in/external/storage.json"}, // files
"my_database", // db_name
"YOUR_ZILLIZ_API_KEY", // api_key
"", // partition_name
{{"projectId", "proj-xxxxxxxxxxxxxxxxxxx"},
{"regionId", "aws-us-west-2"},
{"accessKey", "YOUR_STORAGE_ACCESS_KEY"},
{"secretKey", "YOUR_STORAGE_SECRET_KEY"}});

// job-xxxxxxxxxxxxxxxxxxxxx

With the returned job ID, you can monitor its progress.

python
import json
from pymilvus.bulk_writer import get_import_progress

# Get bulk-insert job progress
resp = get_import_progress(
api_key="YOUR_ZILLIZ_API_KEY",
url="https://api.cloud.zilliz.com",
project_id="proj-xxxxxxxxxxxxxxxxxxx",
region_id="aws-us-west-2",
job_id="job-xxxxxxxxxxxxxxxxxxxxx",
)

print(json.dumps(resp.json(), indent=4))
rust
use milvus::v2::bulk_import::GetImportProgressRequest;

let request = GetImportProgressRequest::builder()
.database_name("my_database")
.project_id("proj-xxxxxxxxxxxxxxxxxxx")
.region_id("aws-us-west-2")
.job_id("job-xxxxxxxxxxxxxxxxxxxxx")
.build()?;

let progress = import_client.get_import_progress(request).await?;
c++
nlohmann::json progress = milvus::BulkImport::GetImportJobProgress(
"https://api.cloud.zilliz.com", // url
"job-xxxxxxxxxxxxxxxxxxxxx", // job_id
"my_database", // db_name
"YOUR_ZILLIZ_API_KEY"); // api_key

Step 6: Create an on-demand cluster​

Once your collection is ready, you need to attach it to an on-demand cluster for on-demand searches. The following command creates a cluster and returns its ID.

bash
export CONTROL_PLANE_ENDPOINT="https://api.cloud.zilliz.com"

curl --request POST \
--url "${CONTROL_PLANE_ENDPOINT}/v2/clusters/createOnDemandCluster" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"projectId": "proj-xxxxxxxxxxxxxxxxxxx",
"regionId": "aws-us-west-2",
"clusterName": "my-on-demand",
"cuSize": 8,
"autoSuspend": 60
}'

# inxx-xxxxxxxxxxxxx

By default, the cluster automatically suspends for 60 seconds after the last request, and you can set it to a value that suits your use cases.

Step 7: Conduct searches.​

When you need to conduct searches, queries, or hybrid searches, you can attach to the on-demand cluster created in the previous step through a session.

python
from pymilvus import MilvusClient

client = MilvusClient(
uri="https://{project-id}.{region}.api.zillizcloud.com",
token="YOUR_API_KEY"
)

session = client.session(cluster_id="inxx-xxxxxxxxxxxxxxx")

# Must match collection vector dimension (example: 768)
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, ..., 0.9029438446296592]

res = session.search(
db_name="my_database",
collection_name="prod_collection",
anns_field="embedding",
data=[query_vector],
limit=3,
output_fields=["product_id", "product_name"]
)
rust
let session = client.session("inxx-xxxxxxxxxxxxxxx")?;

let query_vector = vec![0.3580376395471989f32, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592 /* ...remaining dims */];

let search = session
.search(
SearchRequest::builder()
.collection_name("prod_collection")
.vector_field("embedding")
.vectors(SearchVectors::Float(vec![query_vector]))
.output_fields(["product_id", "product_name"])
.limit(3)
.build()?,
)
.await?;
c++
milvus::MilvusClientV2SessionPtr session;
auto status = client->Session("inxx-xxxxxxxxxxxxxxx", session);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

std::vector<std::vector<float>> query_vectors = {
{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f /* ...remaining dims */}};

milvus::SearchResponse response;
status = session->Search(
milvus::SearchRequest()
.WithDatabaseName("my_database")
.WithCollectionName("prod_collection")
.WithAnnsField("embedding")
.WithLimit(3)
.WithFloatVectors(std::move(query_vectors))
.AddOutputField("product_id")
.AddOutputField("product_name"),
response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

Then, you can explore your data and find the most valuable subset. Then you can connect to a serving cluster, import the data into it, and serve it for production.