pub struct DataGovClient { /* private fields */ }Expand description
Async client for exploring data.gov datasets.
DataGovClient layers ergonomic helpers on top of the lower-level
data_gov_ckan::CkanClient. In addition to search and metadata lookups it
handles download destinations, progress reporting, and colour-aware output
that matches the data-gov CLI defaults.
Implementations§
Source§impl DataGovClient
impl DataGovClient
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Create a new DataGov client with default configuration
Examples found in repository?
5async fn main() -> Result<(), Box<dyn Error>> {
6 println!("🇺🇸 Data.gov Rust Client Demo");
7 println!("================================\n");
8
9 // Create a client
10 let client = DataGovClient::new()?;
11
12 // 1. Search for datasets
13 println!("🔍 Searching for 'climate' datasets...");
14 let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16 println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18 if let Some(results) = &search_results.results {
19 for (i, dataset) in results.iter().enumerate() {
20 println!(
21 "{}. {} ({})",
22 i + 1,
23 dataset.title.as_deref().unwrap_or(&dataset.name),
24 dataset.name
25 );
26
27 // Show resource count
28 let resources = DataGovClient::get_downloadable_resources(dataset);
29 println!(" 📁 {} downloadable resources", resources.len());
30
31 if let Some(notes) = &dataset.notes {
32 let truncated = if notes.len() > 100 {
33 format!("{}...", ¬es[..100])
34 } else {
35 notes.clone()
36 };
37 println!(" 📄 {}", truncated);
38 }
39 println!();
40 }
41 }
42
43 // 2. Get organizations
44 println!("🏛️ Listing government organizations...");
45 let orgs = client.list_organizations(Some(10)).await?;
46 println!("Found {} organizations:", orgs.len());
47 for (i, org) in orgs.iter().enumerate().take(5) {
48 println!(" {}. {}", i + 1, org);
49 }
50 println!();
51
52 // 3. Autocomplete example
53 println!("🔍 Autocomplete for 'energy'...");
54 let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55 println!("Suggestions:");
56 for suggestion in suggestions {
57 println!(" • {}", suggestion);
58 }
59 println!();
60
61 println!("✅ Demo completed! Try the interactive REPL with:");
62 println!(" data-gov");
63 println!();
64 println!("Example CLI commands:");
65 println!(" data-gov search \"electric vehicle\"");
66 println!(" data-gov show electric-vehicle-population-data");
67 println!(
68 " data-gov download electric-vehicle-population-data 0 # By index"
69 );
70 println!(
71 " data-gov download electric-vehicle-population-data \"Comma Separated Values File\" # By name (quoted)"
72 );
73 println!(
74 " data-gov download electric-vehicle-population-data json # Partial match"
75 );
76 println!(" data-gov list organizations");
77 println!(" data-gov --help");
78
79 Ok(())
80}Sourcepub fn with_config(config: DataGovConfig) -> Result<Self>
pub fn with_config(config: DataGovConfig) -> Result<Self>
Create a new DataGov client with custom configuration
Sourcepub async fn search(
&self,
query: &str,
limit: Option<i32>,
offset: Option<i32>,
organization: Option<&str>,
format: Option<&str>,
) -> Result<PackageSearchResult>
pub async fn search( &self, query: &str, limit: Option<i32>, offset: Option<i32>, organization: Option<&str>, format: Option<&str>, ) -> Result<PackageSearchResult>
Search for datasets on data.gov.
§Arguments
query- Search terms (searches titles, descriptions, tags)
Solr syntax: The query string may include Solr-style expressions such as
wildcards (e.g. climat*), phrase searches ("air quality"), and boolean
operators (AND, OR, NOT). When combined with structured filters the
underlying CKAN package_search endpoint interprets q and fq using
Solr semantics, so complex queries are supported.
limit- Maximum number of results (default: 10, max: 1000)offset- Number of results to skip for pagination (default: 0)organization- Filter by organization name (optional)format- Filter by resource format (optional, e.g., “CSV”, “JSON”)
§Examples
Basic search:
let client = DataGovClient::new()?;
let results = client.search("climate data", Some(20), None, None, None).await?;Search with filters:
let results = client.search("energy", Some(10), None, Some("doe-gov"), Some("CSV")).await?;Examples found in repository?
5async fn main() -> Result<(), Box<dyn Error>> {
6 println!("🇺🇸 Data.gov Rust Client Demo");
7 println!("================================\n");
8
9 // Create a client
10 let client = DataGovClient::new()?;
11
12 // 1. Search for datasets
13 println!("🔍 Searching for 'climate' datasets...");
14 let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16 println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18 if let Some(results) = &search_results.results {
19 for (i, dataset) in results.iter().enumerate() {
20 println!(
21 "{}. {} ({})",
22 i + 1,
23 dataset.title.as_deref().unwrap_or(&dataset.name),
24 dataset.name
25 );
26
27 // Show resource count
28 let resources = DataGovClient::get_downloadable_resources(dataset);
29 println!(" 📁 {} downloadable resources", resources.len());
30
31 if let Some(notes) = &dataset.notes {
32 let truncated = if notes.len() > 100 {
33 format!("{}...", ¬es[..100])
34 } else {
35 notes.clone()
36 };
37 println!(" 📄 {}", truncated);
38 }
39 println!();
40 }
41 }
42
43 // 2. Get organizations
44 println!("🏛️ Listing government organizations...");
45 let orgs = client.list_organizations(Some(10)).await?;
46 println!("Found {} organizations:", orgs.len());
47 for (i, org) in orgs.iter().enumerate().take(5) {
48 println!(" {}. {}", i + 1, org);
49 }
50 println!();
51
52 // 3. Autocomplete example
53 println!("🔍 Autocomplete for 'energy'...");
54 let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55 println!("Suggestions:");
56 for suggestion in suggestions {
57 println!(" • {}", suggestion);
58 }
59 println!();
60
61 println!("✅ Demo completed! Try the interactive REPL with:");
62 println!(" data-gov");
63 println!();
64 println!("Example CLI commands:");
65 println!(" data-gov search \"electric vehicle\"");
66 println!(" data-gov show electric-vehicle-population-data");
67 println!(
68 " data-gov download electric-vehicle-population-data 0 # By index"
69 );
70 println!(
71 " data-gov download electric-vehicle-population-data \"Comma Separated Values File\" # By name (quoted)"
72 );
73 println!(
74 " data-gov download electric-vehicle-population-data json # Partial match"
75 );
76 println!(" data-gov list organizations");
77 println!(" data-gov --help");
78
79 Ok(())
80}Sourcepub async fn get_dataset(&self, dataset_id: &str) -> Result<Package>
pub async fn get_dataset(&self, dataset_id: &str) -> Result<Package>
Fetch the full package_show payload for a dataset.
Sourcepub async fn autocomplete_datasets(
&self,
partial: &str,
limit: Option<i32>,
) -> Result<Vec<String>>
pub async fn autocomplete_datasets( &self, partial: &str, limit: Option<i32>, ) -> Result<Vec<String>>
Fetch dataset name suggestions for interactive prompts.
Examples found in repository?
5async fn main() -> Result<(), Box<dyn Error>> {
6 println!("🇺🇸 Data.gov Rust Client Demo");
7 println!("================================\n");
8
9 // Create a client
10 let client = DataGovClient::new()?;
11
12 // 1. Search for datasets
13 println!("🔍 Searching for 'climate' datasets...");
14 let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16 println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18 if let Some(results) = &search_results.results {
19 for (i, dataset) in results.iter().enumerate() {
20 println!(
21 "{}. {} ({})",
22 i + 1,
23 dataset.title.as_deref().unwrap_or(&dataset.name),
24 dataset.name
25 );
26
27 // Show resource count
28 let resources = DataGovClient::get_downloadable_resources(dataset);
29 println!(" 📁 {} downloadable resources", resources.len());
30
31 if let Some(notes) = &dataset.notes {
32 let truncated = if notes.len() > 100 {
33 format!("{}...", ¬es[..100])
34 } else {
35 notes.clone()
36 };
37 println!(" 📄 {}", truncated);
38 }
39 println!();
40 }
41 }
42
43 // 2. Get organizations
44 println!("🏛️ Listing government organizations...");
45 let orgs = client.list_organizations(Some(10)).await?;
46 println!("Found {} organizations:", orgs.len());
47 for (i, org) in orgs.iter().enumerate().take(5) {
48 println!(" {}. {}", i + 1, org);
49 }
50 println!();
51
52 // 3. Autocomplete example
53 println!("🔍 Autocomplete for 'energy'...");
54 let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55 println!("Suggestions:");
56 for suggestion in suggestions {
57 println!(" • {}", suggestion);
58 }
59 println!();
60
61 println!("✅ Demo completed! Try the interactive REPL with:");
62 println!(" data-gov");
63 println!();
64 println!("Example CLI commands:");
65 println!(" data-gov search \"electric vehicle\"");
66 println!(" data-gov show electric-vehicle-population-data");
67 println!(
68 " data-gov download electric-vehicle-population-data 0 # By index"
69 );
70 println!(
71 " data-gov download electric-vehicle-population-data \"Comma Separated Values File\" # By name (quoted)"
72 );
73 println!(
74 " data-gov download electric-vehicle-population-data json # Partial match"
75 );
76 println!(" data-gov list organizations");
77 println!(" data-gov --help");
78
79 Ok(())
80}Sourcepub async fn list_organizations(
&self,
limit: Option<i32>,
) -> Result<Vec<String>>
pub async fn list_organizations( &self, limit: Option<i32>, ) -> Result<Vec<String>>
List the publisher slugs for government organizations.
Examples found in repository?
5async fn main() -> Result<(), Box<dyn Error>> {
6 println!("🇺🇸 Data.gov Rust Client Demo");
7 println!("================================\n");
8
9 // Create a client
10 let client = DataGovClient::new()?;
11
12 // 1. Search for datasets
13 println!("🔍 Searching for 'climate' datasets...");
14 let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16 println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18 if let Some(results) = &search_results.results {
19 for (i, dataset) in results.iter().enumerate() {
20 println!(
21 "{}. {} ({})",
22 i + 1,
23 dataset.title.as_deref().unwrap_or(&dataset.name),
24 dataset.name
25 );
26
27 // Show resource count
28 let resources = DataGovClient::get_downloadable_resources(dataset);
29 println!(" 📁 {} downloadable resources", resources.len());
30
31 if let Some(notes) = &dataset.notes {
32 let truncated = if notes.len() > 100 {
33 format!("{}...", ¬es[..100])
34 } else {
35 notes.clone()
36 };
37 println!(" 📄 {}", truncated);
38 }
39 println!();
40 }
41 }
42
43 // 2. Get organizations
44 println!("🏛️ Listing government organizations...");
45 let orgs = client.list_organizations(Some(10)).await?;
46 println!("Found {} organizations:", orgs.len());
47 for (i, org) in orgs.iter().enumerate().take(5) {
48 println!(" {}. {}", i + 1, org);
49 }
50 println!();
51
52 // 3. Autocomplete example
53 println!("🔍 Autocomplete for 'energy'...");
54 let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55 println!("Suggestions:");
56 for suggestion in suggestions {
57 println!(" • {}", suggestion);
58 }
59 println!();
60
61 println!("✅ Demo completed! Try the interactive REPL with:");
62 println!(" data-gov");
63 println!();
64 println!("Example CLI commands:");
65 println!(" data-gov search \"electric vehicle\"");
66 println!(" data-gov show electric-vehicle-population-data");
67 println!(
68 " data-gov download electric-vehicle-population-data 0 # By index"
69 );
70 println!(
71 " data-gov download electric-vehicle-population-data \"Comma Separated Values File\" # By name (quoted)"
72 );
73 println!(
74 " data-gov download electric-vehicle-population-data json # Partial match"
75 );
76 println!(" data-gov list organizations");
77 println!(" data-gov --help");
78
79 Ok(())
80}Sourcepub async fn autocomplete_organizations(
&self,
partial: &str,
limit: Option<i32>,
) -> Result<Vec<String>>
pub async fn autocomplete_organizations( &self, partial: &str, limit: Option<i32>, ) -> Result<Vec<String>>
Fetch organization name suggestions for interactive prompts.
Sourcepub fn get_downloadable_resources(package: &Package) -> Vec<Resource>
pub fn get_downloadable_resources(package: &Package) -> Vec<Resource>
Return resources that look like downloadable files.
The returned list is filtered to resources that expose a direct URL, are not marked as API endpoints, and advertise a file format.
Examples found in repository?
5async fn main() -> Result<(), Box<dyn Error>> {
6 println!("🇺🇸 Data.gov Rust Client Demo");
7 println!("================================\n");
8
9 // Create a client
10 let client = DataGovClient::new()?;
11
12 // 1. Search for datasets
13 println!("🔍 Searching for 'climate' datasets...");
14 let search_results = client.search("climate", Some(5), None, None, None).await?;
15
16 println!("Found {} results:\n", search_results.count.unwrap_or(0));
17
18 if let Some(results) = &search_results.results {
19 for (i, dataset) in results.iter().enumerate() {
20 println!(
21 "{}. {} ({})",
22 i + 1,
23 dataset.title.as_deref().unwrap_or(&dataset.name),
24 dataset.name
25 );
26
27 // Show resource count
28 let resources = DataGovClient::get_downloadable_resources(dataset);
29 println!(" 📁 {} downloadable resources", resources.len());
30
31 if let Some(notes) = &dataset.notes {
32 let truncated = if notes.len() > 100 {
33 format!("{}...", ¬es[..100])
34 } else {
35 notes.clone()
36 };
37 println!(" 📄 {}", truncated);
38 }
39 println!();
40 }
41 }
42
43 // 2. Get organizations
44 println!("🏛️ Listing government organizations...");
45 let orgs = client.list_organizations(Some(10)).await?;
46 println!("Found {} organizations:", orgs.len());
47 for (i, org) in orgs.iter().enumerate().take(5) {
48 println!(" {}. {}", i + 1, org);
49 }
50 println!();
51
52 // 3. Autocomplete example
53 println!("🔍 Autocomplete for 'energy'...");
54 let suggestions = client.autocomplete_datasets("energy", Some(5)).await?;
55 println!("Suggestions:");
56 for suggestion in suggestions {
57 println!(" • {}", suggestion);
58 }
59 println!();
60
61 println!("✅ Demo completed! Try the interactive REPL with:");
62 println!(" data-gov");
63 println!();
64 println!("Example CLI commands:");
65 println!(" data-gov search \"electric vehicle\"");
66 println!(" data-gov show electric-vehicle-population-data");
67 println!(
68 " data-gov download electric-vehicle-population-data 0 # By index"
69 );
70 println!(
71 " data-gov download electric-vehicle-population-data \"Comma Separated Values File\" # By name (quoted)"
72 );
73 println!(
74 " data-gov download electric-vehicle-population-data json # Partial match"
75 );
76 println!(" data-gov list organizations");
77 println!(" data-gov --help");
78
79 Ok(())
80}Sourcepub fn get_resource_filename(
resource: &Resource,
fallback_name: Option<&str>,
resource_index: Option<usize>,
) -> String
pub fn get_resource_filename( resource: &Resource, fallback_name: Option<&str>, resource_index: Option<usize>, ) -> String
Pick a filesystem-friendly filename for a resource download. Pick a filesystem-friendly filename for a resource download.
§Arguments
resource- The resource to generate a filename forfallback_name- Optional fallback name if resource has no nameresource_index- Optional index to append to prevent conflicts when multiple resources have the same name
When downloading multiple resources, the index should be provided to ensure unique filenames even when resources have duplicate names.
Sourcepub async fn download_resource(
&self,
resource: &Resource,
output_dir: Option<&Path>,
) -> Result<PathBuf>
pub async fn download_resource( &self, resource: &Resource, output_dir: Option<&Path>, ) -> Result<PathBuf>
Download a single resource to the specified directory.
§Arguments
resource- The resource to downloadoutput_dir- Directory where the file will be saved. If None, uses the base download directory.
Returns the full path where the file was saved.
Sourcepub async fn download_resources(
&self,
resources: &[Resource],
output_dir: Option<&Path>,
) -> Vec<Result<PathBuf>> ⓘ
pub async fn download_resources( &self, resources: &[Resource], output_dir: Option<&Path>, ) -> Vec<Result<PathBuf>> ⓘ
Sourcepub async fn validate_download_dir(&self) -> Result<()>
pub async fn validate_download_dir(&self) -> Result<()>
Check if the base download directory exists and is writable
Sourcepub fn download_dir(&self) -> PathBuf
pub fn download_dir(&self) -> PathBuf
Get the current base download directory
Sourcepub fn ckan_client(&self) -> &CkanClient
pub fn ckan_client(&self) -> &CkanClient
Get the underlying CKAN client for advanced operations