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
This commit is contained in:
224
examples/search_metadata.rs
Normal file
224
examples/search_metadata.rs
Normal file
@@ -0,0 +1,224 @@
|
||||
//! 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(())
|
||||
}
|
||||
Reference in New Issue
Block a user