Files
immich-sdk/examples/search_metadata.rs
Joakim Hulthe 2e7db3b35a Add integration testing infrastructure with Podman Compose
- Add docker/podman-compose.yml for Immich server (no ML)
- Add test-data/sample-photos/ with 3 public domain images
- Add scripts/start-immich.sh for container startup + admin/API key creation
- Add scripts/seed-data.sh for uploading test photos and creating albums
- Add scripts/stop-immich.sh for cleanup with volume destruction
- Add scripts/run-example.sh wrapper (fixed env var export)
- Update examples to use IMMICH_URL and IMMICH_API_KEY env vars
- Add .github/workflows/integration-test.yml for CI
- Update assets.list() to use /search/metadata endpoint
- Update AGENTS.md with example running instructions
- Add 5 new examples: search_metadata, album_management, timeline_browsing,
  delete_assets, server_info
2026-04-14 20:13:30 +00:00

225 lines
7.4 KiB
Rust

//! Example: Search for assets using metadata filters
//!
//! This example demonstrates the powerful search capabilities of Immich
//!
//! This example uses environment variables for configuration:
//! - IMMICH_URL: The Immich server URL (defaults to http://localhost:2283)
//! - IMMICH_API_KEY: Your API key (required)
use chrono::Duration;
use chrono::Utc;
use immich_sdk::Client;
use immich_sdk::models::AssetOrder;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure the client from environment variables
let url = std::env::var("IMMICH_URL").unwrap_or_else(|_| "http://localhost:2283".to_string());
let api_key =
std::env::var("IMMICH_API_KEY").expect("IMMICH_API_KEY environment variable not set");
// Create a client
let client = Client::from_url(&url)?.with_api_key(api_key);
// Get total asset count
let all_results = client.search().metadata().size(1).execute().await?;
println!("Total assets in library: {}", all_results.assets.total);
println!();
// =================================================================
// Example 1: Search for favorite assets
// =================================================================
println!("=== Example 1: Search for favorites ===");
let favorites = client.search().metadata().favorite(true).execute().await?;
println!("Found {} favorite assets", favorites.assets.total);
if favorites.assets.items.is_empty() {
println!("No favorite assets found. Try marking some photos as favorites in Immich.");
} else {
for asset in favorites.assets.items.iter().take(3) {
println!(" - {}: {}", asset.id, asset.original_file_name);
}
}
println!();
// =================================================================
// Example 2: Search by asset type (images only)
// =================================================================
println!("=== Example 2: Search for images only ===");
let images = client
.search()
.metadata()
.asset_type(immich_sdk::models::AssetType::Image)
.size(5)
.execute()
.await?;
println!("Found {} image assets", images.assets.total);
for asset in &images.assets.items {
println!(" - {}", asset.original_file_name);
}
println!();
// =================================================================
// Example 3: Search by date range
// =================================================================
// Search for assets created in the last 30 days
println!("=== Example 3: Search by date range (last 30 days) ===");
let thirty_days_ago = Utc::now() - Duration::days(30);
let recent = client
.search()
.metadata()
.created_after(thirty_days_ago)
.execute()
.await?;
println!(
"Found {} assets created in the last 30 days",
recent.assets.total
);
if !recent.assets.items.is_empty() {
println!("Recent assets:");
for asset in recent.assets.items.iter().take(3) {
println!(
" - {} (created: {})",
asset.original_file_name,
asset.created_at.format("%Y-%m-%d")
);
}
}
println!();
// =================================================================
// Example 4: Search by city (if photos have location data)
// =================================================================
println!("=== Example 4: Search by city (location-based) ===");
let city_results = client
.search()
.metadata()
.city("New York")
.size(10)
.execute()
.await?;
if city_results.assets.total > 0 {
println!("Found {} assets from New York", city_results.assets.total);
for asset in &city_results.assets.items {
println!(" - {}", asset.original_file_name);
}
} else {
println!("No assets found from New York. Try searching for photos with GPS location data.");
}
println!();
// =================================================================
// Example 5: Combined filters (favorites + date range)
// =================================================================
println!("=== Example 5: Combined filters (favorites + recent) ===");
let recent_favorites = client
.search()
.metadata()
.favorite(true)
.created_after(thirty_days_ago)
.execute()
.await?;
println!(
"Found {} favorite assets from the last 30 days",
recent_favorites.assets.total
);
if !recent_favorites.assets.items.is_empty() {
for asset in &recent_favorites.assets.items {
println!(" - {}", asset.original_file_name);
}
}
println!();
// =================================================================
// Example 6: Search with pagination
// =================================================================
println!("=== Example 6: Pagination ===");
println!("Retrieving results with pagination (page 1, size 2)...");
let page1 = client
.search()
.metadata()
.page(1)
.size(2)
.order(AssetOrder::Desc)
.execute()
.await?;
println!(
"Page 1: {} of {} assets",
page1.assets.count, page1.assets.total
);
for asset in &page1.assets.items {
println!(" - {}", asset.original_file_name);
}
// Check if there are more pages
if page1.assets.next_page.is_some() {
println!("More results available on next page!");
// Fetch page 2
let page2 = client
.search()
.metadata()
.page(2)
.size(2)
.order(AssetOrder::Desc)
.execute()
.await?;
println!(
"\nPage 2: {} of {} assets",
page2.assets.count, page2.assets.total
);
for asset in &page2.assets.items {
println!(" - {}", asset.original_file_name);
}
} else if page1.assets.total > 0 {
println!("No more pages available.");
}
println!();
// =================================================================
// Example 7: Search with ordering
// =================================================================
println!("=== Example 7: Search with ordering (oldest first) ===");
let oldest = client
.search()
.metadata()
.order(AssetOrder::Asc)
.size(5)
.execute()
.await?;
println!("Oldest {} assets:", oldest.assets.items.len());
for asset in &oldest.assets.items {
println!(
" - {} (created: {})",
asset.original_file_name,
asset.created_at.format("%Y-%m-%d")
);
}
println!();
// =================================================================
// Summary
// =================================================================
println!("=== Search Summary ===");
println!("Demonstrated search filters:");
println!(" - Favorite status (is_favorite)");
println!(" - Asset type (IMAGE/VIDEO)");
println!(" - Date range (created_after, created_before)");
println!(" - Location (city, country)");
println!(" - Combined filters");
println!(" - Pagination (page, size)");
println!(" - Ordering (asc/desc)");
println!();
println!("Total assets in library: {}", all_results.assets.total);
Ok(())
}