This is a test project that lets you search the most suitable recipes for the ingredients that you have at your disposal. This is the backend part which has an API for searching recipes based on given ingredients, using Full-Text Search of PostgreSQL.
- Using Full Text Search functionality of PostgreSQL for normalizing both input and database data, as well as making the search more forgiving than
LIKE
orILIKE
operators - Ranking search results by similarity to the given query (using ts_rank function in PostgreSQL)
- Ordering search results by attributes like 'ratings', 'ingredients' (amount of ingredients)
- Ordering can be controlled by the user as well
Given the "human" format of the data (ingredients are unnormalized but they contain useful details) I decided to not try normalizing the data before writing it to the database and using relations, but instead using approach that can handle the variability of the data. I used a single table "recipes" which contains "ingredients" as one of its columns, and the search by ingredients is performed by the built-in Full Text Search functionality of PostgreSQL, which normalizes the data as well as the query during the search, and it also ranks by similarity to the given query. I found this approach to be pretty accurate with giving the recipes that contain all or almost all of the specified ingredients.
- Having some basic pasta-related ingredients by a coincidence would return some pasta recipes:
curl --location --request GET 'localhost:3000/api/v1/recipes' \
--header 'Content-Type: application/json' \
--data '{
"order_by": "relevance",
"ingredients": [
"spaghetti",
"olive oil",
"garlic",
"cherry tomatoes",
"basil",
"pasta",
"black pepper",
"parmesan",
"salt"
]
}'
- Given the snapshot of my kitchen:
curl --location --request GET 'localhost:3000/api/v1/recipes' \
--header 'Content-Type: application/json' \
--data '{
"order_by": "relevance",
"ingredients": [
"spaghetti",
"pasta",
"olive oil",
"garlic",
"tomato",
"basil",
"rosemary",
"water",
"black pepper",
"parmesan",
"salt",
"milk",
"coriander",
"bread",
"mozzarella",
"champignon mushrooms",
"zucchini",
"chicken breast"
]
}'
.. I found that "Baked Chicken and Zucchini", "Skinny Pasta Bake with Ground Turkey" or "Chicken Pesto Sandwich" are really the recipes that I can technically cook (though by replacing turkey with chicken)
- Make sure you have Ruby 3.3.0 or newer installed
- It is recommended to have PostgreSQL 16.1 or newer (Alternatively, you can use docker-compose from parent repo running backend, frontend and postgresql on your machine)
- Run
bundle
cp .env.sample .env
cp .env.sample.test .env.test
- Download the recipes: $
mkdir db/seeds && wget https://pennylane-interviewing-assets-20220328.s3.eu-west-1.amazonaws.com/recipes-en.json.gz && gzip -dc recipes-en.json.gz > db/seeds/recipes-en.json && rm recipes-en.json.gz
- Run
rails db:create db:migrate db:seed
- Run rails server (or make sure you are running it with docker-compose)
- Also run the React app
See the parent mealtime-platform repo
Go to
- Enter the ingredients you have at your disposal
- The app will search through the database for the most relevant recipes that contain all or most of the specified keywords. It also ranks results by similarity to the given query.
- VoilĂ !