4

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

Community
  • 1
  • 1
Ken Cochrane
  • 75,357
  • 9
  • 52
  • 60

3 Answers3

2

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.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • That was what I was looking for, I'll try it out and see if that works for me. If I have to change anything, I'll let you know so you can update your answer. – Ken Cochrane Jun 19 '12 at 18:35
  • 2
    ``model_attr="_meta__verbose_name_plural"`` works. It's ugly, but not as ugly as adding a stupid method to X different models. I blame Haystack. – miracle2k Jan 03 '13 at 19:12
1

The best solution is to regroup objects in django template through regroup django'stemplatetag associated with dictsort django's template filter (regroup works only with ordered queryset):

{% with page.object_list as results %}

   {% regroup results|dictsort:"model_name" by model_name as grouped_objects %}

   {% for ct in grouped_objects %}

      {{ ct.grouper }} (Total: {{ct.list|length}}

      {% for result in ct.list %}

      <p><a href="{{ result.object.get_absolute_url }}">{{ result.object }}</a></p>

      {% endfor %}

   {% empty %}

      <p>No results found.</p>

   {% endfor %}

{% endwith %}

If you don't want to lose your original order be sure to pas the SearchQueryset ordered by ('model_name',*your_order_fields)

madeng84
  • 377
  • 1
  • 7
0

Try the following:

sqs1 = SearchQuerySet().models(Note).facet('author')
print sqs1.facet_counts()

sqs2 = SearchQuerySet().models(Comment).facet('author')
print sqs2.facet_counts()

sqs3 = SearchQuerySet().models(Article).facet('author')
print sqs3.facet_counts()

# multiple models are allowed as well:
sqs4 = SearchQuerySet().models(Note, Article).facet('author')
print sqs4.facet_counts()

This limits the SearchQuerySet to one or more models before computing the facet counts.

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180