简体   繁体   中英

How to use Django Haystack EdgeNGrams with Many-to-Many field?

I've recently been trying to implement full text search on my webapp with Django Haystack (v2.1.0) with Elasticsearch (v0.90.5) as my search engine. My goal is to be able to, with one query, search through a title field, key line field, and an authors field for a given Song object. Here is my code:

Models.py

class Song(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    key_line = models.CharField(max_length=300, blank=True)

    def __unicode__(self):
        return self.title

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    middle_name = models.CharField(max_length=30, blank=True)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail')

    def __unicode__(self):
        if self.middle_name:
            return u'%s %s %s' % (self.first_name, self.middle_name, self.last_name)
        else:
            return u'%s %s' % (self.first_name, self.last_name)

    class Meta:
        ordering = ('last_name','first_name')

Search_index.py

from haystack import indexes
from songs.models import Song

class SongIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    content_auto = indexes.EdgeNgramField(model_attr='title')
    content_auto = indexes.EdgeNgramField(model_attr='key_line')
    authors = indexes.MultiValueField()
    content_auto = indexes.EdgeNgramField(model_attr='authors')

    def get_model(self):
        return Song

    def prepare_authors(self, object):
        return [author.last_name for author in object.authors.all()]

    def index_queryset(self, using=None):
        return self.get_model().objects.all()

song_text.txt

{{ object.title}}
{{ object.key_line}}
{% for author in object.authors.all %}
    {{ author.last_name}}
{% endfor %}

I'm sure my search_index.py is terribly wrong for the authors but I was getting desperate. I've been able to get the title and the key_line to work properly in that if i type in a query, I get results that have the query in the title or have the query in the key line. Performing the same test but instead querying the author's last name doesn't give me results with that author.

I've gone through the documentation and though I've found some information on indexing related fields, I haven't been able to find anything specific related to using EdgeNGrams with a related field. Is this possible to do? Ideally, I'd like to be able to query over the author's first, middle, and last name.

Thanks in advance for any help you can give! Let me know if you need any more information.

Similar problem is addressed @ Haystack search on a many to many field is not working

def prepare_category(self, obj):
       return [category.name for category in obj.category_set.all()]

Your code should be ;

def prepare_authors(self, object):
    return [author.last_name for author in object.authors_set.all()]

Change song_text.txt to ;

{{ object.title}}
{{ object.key_line}}
{% for author in object.authors.all %}
    {{ author.first_name}}
    {{ author.middle_name}}
    {{ author.last_name}}
{% endfor %}

Changing object.authors.all() to object.authors_set.all() should solve this problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM