Django manytomany field, how to get check for 80% subset/ match?
I have a Django db with cooking recipes. I want to query all users who have at least 80% ingredients to make a recipe. How do I achieve this?
Or how do I query for users who are missing only 1 ingredient for the recipe?
models.py
class ingredient(models.Model):
id = models.AutoField("id",max_length = 100, primary_key=True)
name=models.CharField("Ingredient", max_length=100)
def __unicode__ (self):
return self.name
class user(models.Model):
id = models.AutoField("id",max_length = 100, primary_key=True
ingredient = models.ManyToManyField(ingredient,blank=True)
def __unicode__ (self):
return str(self.id)
class recipe(models.Model):
id = models.AutoField("id", max_length=100, primary_key=True)
recipe_ingredient = models.ManyToManyField(ingredient,related_name='recipe_ingredient',blank=True)
def __unicode__ (self):
return self.id
I would use django-haystack for this, you can setup an index for your job_opening
model and index all the ingredients:
class JobOpeningIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
recipe_ingredient = indexes.MultiValueField()
def prepare_recipe_ingredient(self, obj):
return [i.name for i in obj.recipe_ingredient.all()]
def get_model(self):
return job_opening
def index_queryset(self, using=None):
return self.get_model().objects.all()
After the indexes has been created you can just do a filter by ingredient or list of ingredients, haystack will return all objects which match the search criteria, sorted by relevance. You can then just map the 80%
to a score in relevance and filter out the items with a relevancy lower that your required amount.
SearchQuerySet().models(job_opening).filter(recipe_ingredient__in=['ingredient1', 'ingredient2', 'ingredient3'])
EDIT
After reading the edited question, we basically have to use recipe
where we used job_opening
. And it seems like you want to find relevant users, not recipes. To accomplish this, you would have to index the user model instead of the original job_opening
model:
class UserIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
ingredient = indexes.MultiValueField()
def prepare_ingredient(self, obj):
return [i.name for i in obj.ingredient.all()]
def get_model(self):
return user
def index_queryset(self, using=None):
return self.get_model().objects.all()
After the index has been created, you can then do the filter like this:
myrecipe = recipe.objects.get(...)
SearchQuerySet().models(user).filter(ingredient__in=myrecipe.recipe_ingredient.all())
链接地址: http://www.djcxy.com/p/27290.html