I have to implement a search function which will be fault tolerant.
Currently, I have the following situation:
Models:
class Tag(models.Model):
name = models.CharField(max_length=255)
class Illustration(models.Model):
name = models.CharField(max_length=255)
tags = models.ManyToManyField(Tag)
Query:
queryset.annotate(similarity=TrigramSimilarity('name', fulltext) + TrigramSimilarity('tags__name', fulltext))
Example data:
Illustrations:
ID | Name | Tags |
---|--------|-------------------|
1 | "Dog" | "Animal", "Brown" |
2 | "Cat" | "Animals" |
Illustration has Tags:
ID_Illustration | ID_Tag |
----------------|--------|
1 | 1 |
1 | 2 |
2 | 3 |
Tags:
ID_Tag | Name |
-------|----------|
1 | Animal |
2 | Brown |
3 | Animals |
When I run the query with "Animal"
, the similarity for "Dog"
should be higher than for "Cat"
, as it is a perfect match.
Unfortunately, both tags are considered together somehow.
Currently, it looks like it's concatenating the tags in a single string and then checks for similarity:
TrigramSimilarity("Animal Brown", "Animal") => X
But I would like to adjust it in a way that I will get the highest similarity between an Illustration
instance name and its tags:
Max([
TrigramSimilarity('Name', "Animal"),
TrigramSimilarity("Tag_1", "Animal"),
TrigramSimilarity("Tag_2", "Animal"),
]) => X
Edit1: I'm trying to query all Illustration, where either the title or one of the tags has a similarity bigger than X.
Edit2: Additional example:
fulltext = 'Animal'
TrigramSimilarity('Animal Brown', fulltext) => x TrigramSimilarity('Animals', fulltext) => y
Where x < y
But what I want is actually
TrigramSimilarity(Max(['Animal', 'Brown]), fulltext) => x (Similarity to Animal) TrigramSimilarity('Animals', fulltext) => y
Where x > y
TrigramSimilarity
a python function or does it translate to SQL? If it's python, I don't think you can use it in theannotate
call as you're trying to do. – Leta