Search code examples
djangodjango-haystackwhoosh

Finding the number of haystack results by model type?


Let's say I have 3 models (Note, Comment, Article) that I want to search using django-haystack and I setup 3 indexes like this.

class NoteIndex(SearchIndex):
    text = CharField(document=True, use_template=True)
    author = CharField(model_attr='user', faceted=True)
    pub_date = DateTimeField(model_attr='pub_date')

class CommentIndex(SearchIndex):
    text = CharField(document=True, use_template=True)
    author = CharField(model_attr='user', faceted=True)
    pub_date = DateTimeField(model_attr='pub_date')

class ArticleIndex(SearchIndex):
    text = CharField(document=True, use_template=True)
    author = CharField(model_attr='user', faceted=True)
    pub_date = DateTimeField(model_attr='pub_date')

When I get my results, I'm able to use the author facet to show the number of results by author.

>>> from haystack.query import SearchQuerySet
>>> sqs = SearchQuerySet().facet('author')
>>> sqs.facet_counts()
{
    'dates': {},
    'fields': {
        'author': [
            ('john', 4),
            ('daniel', 2),
            ('sally', 1),
            ('terry', 1),
        ],
    },
    'queries': {}
}

But how can I find out how many results by Model type? For example.

Notes: 4 Comment: 2 Article: 1

Ideally I would like to filter on it, like a normal facet. I'm using the FacetedModelSearchForm now, and I can see the model types, just can't get the count values. Is this possible? If so, how?

Similar Questions:

It looks like someone else asked this question as well, but maybe didn't ask the question clear enough.

Django Haystack faceting on the model type

This one is similar but they just want to order by the content type, I want the count by content type.

Using django-haystack, how do I order results by content type

Here is another similar question, but not quite the same, and once again no answer as well.

Django Haystack Faceting examples


Solution

  • Have you tried just creating another facet for that? The only potentially difficult part would be getting the model name. Most likley, you would want to use verbose_name so it's more readable, which you can get from _meta.verbose_name. However, something like the following code probably wouldn't work:

    model = CharField(model_attr='_meta.verbose_name', faceted=True)
    

    So, you could simply add a method to your model to just return this value:

    def get_model_name(self):
        return self._meta.verbose_name
    

    Then:

    model = CharField(model_attr='get_model_name', faceted=True)
    

    All of this is untested though, as I've never needed to do this myself.