I have a model with multiple fields that I want to be searchable, and I want to use a search vector in the database for searching. Let’s say my model is Song, and a song has several searchable fields: a title, a filename, and comment text. In addition, there is also a SearchVector field called search_document that is meant to be used in the search query. Here’s a simplified version of the class:
class Song(models.Model):
filename=models.CharField()
title=models.CharField()
comment_text=models.TextField()
search_document=SearchVectorField()
The search vector is populated via a signal. Whenever an object is saved, the signal creates a search vector using the following weighting:
def index_components(self):
return {
'A': self.title,
'B': self.filename,
'C': self.comment_text
}
The method called in the signal looks like this:
def make_updater(instance):
components = instance.index_components()
pk = instance.pk
def on_commit():
search_vectors = []
for weight, text in components.items():
search_vectors.append(
SearchVector(Value(text, output_field=TextField()), weight=weight)
)
instance.__class__.objects.filter(pk=pk).update(
search_document=reduce(operator.add, search_vectors)
)
return on_commit
And finally, a search query on the Song class looks like this:
Song.objects.annotate(
type=Value('song', output_field=CharField()),
rank=rank_annotation
).filter(
search_document=query
).values('pk', 'type', 'rank')
This works, but it searches for all three fields together. I would like to also be able to search only for a particular field. In particular, I would like the search for comment_text to be optional, and to be able to search for title and filename without comment_text.
Is it possible to modify my query to only search for title and filename without comment_text while still keeping all three within the same SearchVectorField? Or will I need to store comment_text into a different SearchVectorField?