Skip to content

Commit

Permalink
Merge pull request #5 from timkolloch/features/use-fdcId-field
Browse files Browse the repository at this point in the history
Using FDC ID field, when no URL is given
  • Loading branch information
timkolloch authored Aug 7, 2024
2 parents d9e38b1 + 1f34f8d commit a6c5b7a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ Because adding all the properties to a food by hand is quite annoying I built th
## How does it work?
1. The program reads the [appsettings.json](./appsettings.template.json) to find the Tandoor instance and to get the needed API-Keys for Tandoor and the USDA FDC database.
2. After that all properties and all foods are retrieved from the Tandoor instance.
3. For each food item retrieved from Tandoor the FDC ID of that food item (retrieved from the URL of the `Food`) is used to query the FDC database for nutrients.
3. For each food item retrieved from Tandoor the FDC ID of that food item (the ID is retrieved primarily from the "URL" field of a `Food`. If no URL is given the program tries to get it from the "FDC ID" field) is used to query the FDC database for nutrients.
4. All nutrients of a food item are retrieved, then the nutrients that are not present in Tandoor are filtered out.
5. The data retrieved from the FDC database is added to the Tandoor food. **Note that all properties previously associated with the Tandoor food are overwritten.**
6. The updated food is pushed to the Tandoor database.

## Prerequisites
1. Create an API key for your Tandoor instance under `<your-tandoor-endpoint>/settings` in the API section. Make sure the token has `read write` as the scope.
2. Create an API key for the USDA FDC database by signing up [here](https://fdc.nal.usda.gov/api-key-signup.html). The API key will be sent to you via e-mail.
3. Open the FDC page for every food you want to update (e.g. [this](https://fdc.nal.usda.gov/fdc-app.html#/food-details/169661/nutrients) for maple syrup) and copy the URL into the "URL" field of the food. The field can be found by editing a food item and going to the "More" section.
3. Open the FDC page for every food you want to update (e.g. [this](https://fdc.nal.usda.gov/fdc-app.html#/food-details/169661/nutrients) for maple syrup)
- Either copy the URL into the "URL" field of the food. The field can be found by editing a food item and going to the "More" section.
- Or go to the admin view of your foods `<yout-tandoor-endpoint/admin/cookbook/food/` and edit the food there to enter the FDC ID.
- Note that the URL will be preferred if URL and FDC ID are set.
4. Make sure that every property you have created in Tandoor also has the corresponding FDC ID assigned so the matching can work.

## Usage
Expand Down
43 changes: 33 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,12 @@ fn main(){
let mut updated_foods: i32 = 0;
let mut not_updated_foods: i32 = 0;
let mut no_fdc_id: i32 = 0;
let re = Regex::new(r"food-details/(\d+)/nutrients").unwrap();
for food in tandoor_foods{
// Get data from USDA
let fdc_id: i32;
if let Some(food_url) = food.url.clone() {
if let Some(caps) = re.captures(&*food_url) {
fdc_id = (&caps[1]).parse().unwrap();
}else{
println!("Food {} does not have a FDC ID and will not be updated.", food.name);
no_fdc_id += 1;
continue;
}
} else {
if let Some(id) = get_fdc_id(&food){
fdc_id = id
}else{
println!("Food {} does not have a FDC ID and will not be updated.", food.name);
no_fdc_id += 1;
continue;
Expand Down Expand Up @@ -265,3 +258,33 @@ fn update_food(client: &Client, tandoor_endpoint: &String, tandoor_api_key: &Str
.error_for_status()?;
Ok(true)
}

/// Gets the FDC ID from a given food (either from the URL field or the FDC ID field).
/// ### Parameters
/// - food: The food for which the FDC ID should be retrieved.
/// ### Returns
/// Option<i32> containing the FDC ID or None if no FDC ID was found in the URL or FDC ID field.
fn get_fdc_id(food: &InternalTandoorFood) -> Option<i32>{

// Closure to handle fallback to FDC ID field.
let get_fdc_id_from_field = || {
if let Some(fdc_id_of_food) = food.fdc_id.clone() {
Some(fdc_id_of_food)
} else {
None
}
};

let re = Regex::new(r"food-details/(\d+)/nutrients").unwrap();
// If URL is set use that to get FDC ID
// if no URL is set or no FDC ID can be matched from the URL, use FDC ID field.
return if let Some(food_url) = food.url.clone() {
if let Some(caps) = re.captures(&*food_url) {
Some((&caps[1]).parse().unwrap())
} else {
get_fdc_id_from_field()
}
} else {
get_fdc_id_from_field()
}
}
2 changes: 2 additions & 0 deletions src/models/tandoor/internal_tandoor_food.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub struct InternalTandoorFood {
pub id: i32,
/// The name of the food item.
pub name: String,
/// The FDC ID of the food.
pub fdc_id: Option<i32>,
/// A list of all [InternalTandoorFoodProperty] that this food has at the moment.
pub properties: Vec<InternalTandoorFoodProperty>,
/// URL of the food in the FDC database.
Expand Down

0 comments on commit a6c5b7a

Please sign in to comment.