1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-05 13:35:23 +02:00

feat: Improved Ingredient Matching (#2535)

* added normalization to foods and units

* changed search to reference new normalized fields

* fix tests

* added parsed food matching to backend

* prevent pagination from ordering when searching

* added extra fuzzy matching to sqlite ing matching

* added tests

* only apply search ordering when order_by is null

* enabled post-search fuzzy matching for postgres

* fixed postgres fuzzy search test

* idk why this is failing

* 🤦

* simplified frontend ing matching
and restored automatic unit creation

* tightened food fuzzy threshold

* change to rapidfuzz

* sped up fuzzy matching with process

* fixed units not matching by abbreviation

* fast return for exact matches

* replace db searching with pure fuzz

* added fuzzy normalization

* tightened unit fuzzy matching thresh

* cleaned up comments/var names

* ran matching logic through the dryer

* oops

* simplified order by application logic
This commit is contained in:
Michael Genson 2023-09-15 12:19:34 -05:00 committed by GitHub
parent 084ad4228b
commit 2dfbe9f08d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 738 additions and 97 deletions

View file

@ -0,0 +1,71 @@
"""empty message
Revision ID: 0341b154f79a
Revises: bcfdad6b7355
Create Date: 2023-09-01 14:55:42.166766
"""
import sqlalchemy as sa
from sqlalchemy import orm, select
from alembic import op
from mealie.db.models.recipe.ingredient import IngredientFoodModel, IngredientUnitModel
# revision identifiers, used by Alembic.
revision = "0341b154f79a"
down_revision = "bcfdad6b7355"
branch_labels = None
depends_on = None
def populate_normalized_fields():
bind = op.get_bind()
session = orm.Session(bind=bind)
units = session.execute(select(IngredientUnitModel)).scalars().all()
for unit in units:
if unit.name is not None:
unit.name_normalized = IngredientUnitModel.normalize(unit.name)
if unit.abbreviation is not None:
unit.abbreviation_normalized = IngredientUnitModel.normalize(unit.abbreviation)
session.add(unit)
foods = session.execute(select(IngredientFoodModel)).scalars().all()
for food in foods:
if food.name is not None:
food.name_normalized = IngredientFoodModel.normalize(food.name)
session.add(food)
session.commit()
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("ingredient_foods", sa.Column("name_normalized", sa.String(), nullable=True))
op.create_index(op.f("ix_ingredient_foods_name_normalized"), "ingredient_foods", ["name_normalized"], unique=False)
op.add_column("ingredient_units", sa.Column("name_normalized", sa.String(), nullable=True))
op.add_column("ingredient_units", sa.Column("abbreviation_normalized", sa.String(), nullable=True))
op.create_index(
op.f("ix_ingredient_units_abbreviation_normalized"),
"ingredient_units",
["abbreviation_normalized"],
unique=False,
)
op.create_index(op.f("ix_ingredient_units_name_normalized"), "ingredient_units", ["name_normalized"], unique=False)
# ### end Alembic commands ###
populate_normalized_fields()
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f("ix_ingredient_units_name_normalized"), table_name="ingredient_units")
op.drop_index(op.f("ix_ingredient_units_abbreviation_normalized"), table_name="ingredient_units")
op.drop_column("ingredient_units", "abbreviation_normalized")
op.drop_column("ingredient_units", "name_normalized")
op.drop_index(op.f("ix_ingredient_foods_name_normalized"), table_name="ingredient_foods")
op.drop_column("ingredient_foods", "name_normalized")
# ### end Alembic commands ###