0

Please note I am using elasticsearch as my backend.

Taggit tags associated with my model, ObjectA, do not seem to come through in my index using the django setting

HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

When I list the index documents using

http://localhost:9200/_search

and view the index record for an ObjectA instance I inserted in the DB the 'tags' element appears as

"tags": []

It is only after I run

manage.py rebuild_index [or update_index]

do the tags appear i.e.

"tags": ["tag-a", "tag-b"]

The interesting thing is 'title', 'description' show-up automatically without running rebuild_index/update_index.

objecta_text.txt

{{ object.title }}
{{ object.description }}
{% for tag in object.tags.all %} {{ tag.name }} {% endfor %}

search_indexes.py

class ObjectAIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    title = indexes.CharField(model_attr='title')
    description = indexes.CharField(model_attr='description', null=True)
    tags = indexes.MultiValueField()

    def get_model(self):
        return ObjectA

    def prepare_tags(self, obj):
     return [tag.name for tag in obj.tags.all()] 

Any suggestions on how to get the tags to show up in the index document without invoking rebuild_index?

1 Answers1

1

Not sure if you already figured this out, but the reason your index doesn't contain the tags after save is that they are not yet stored when the signal processor handles the index update. One hacky way to solve this is to extend haystack.signals.RealtimeSignalProcessor to trigger on updates of related models. Here is an example that would update the index for any tagged model.

signals.py

from haystack.signals import RealtimeSignalProcessor


class RelatedRealtimeSignalProcessor(RealtimeSignalProcessor):
    """
    Extension to haystack's RealtimeSignalProcessor not only causing the
    search_index to update on saved model, but also for related effected models
    """

    def handle_save(self, sender, instance, **kwargs):
        super(RelatedRealtimeSignalProcessor, self).handle_save(
            sender,
            instance,
            **kwargs
        )
        self.handle_related(sender, instance)

    def handle_delete(self, sender, instance, **kwargs):
        super(RelatedRealtimeSignalProcessor, self).handle_delete(
            sender,
            instance,
            **kwargs
        )
        self.handle_related(sender, instance)

    def handle_related(self, sender, instance):
        for related in self.get_related_models(sender, instance):
            super(RelatedRealtimeSignalProcessor, self).handle_save(
                related['sender'],
                related['instance']
            )

    def get_related_models(self, sender, instance):
        from taggit.models import TaggedItem

        related = []
        if sender == TaggedItem:
            related.append({
                'sender': instance.content_object.__class__,
                'instance': instance.content_object
            })
        return related

PS. Don't forget to update your HAYSTACK_SIGNAL_PROCESSOR = '<app>.signals.RealtimeSignalProcessor'

niklasae
  • 1,097
  • 1
  • 9
  • 8