1

I was reading the docs and some questions around here and couldn't understand how can I return a query that has fields indexed in two different classes. Let me put the code below:

Here I have the classes:

class T031003Index(RealTimeSearchIndex):
text = CharField(document=True, use_template=True)
C003INST = IntegerField(model_attr='C003INST')
C003CHCD = CharField(model_attr='C003CHCD')
C003MTR = CharField(model_attr='C003MTR')
C003RZSC = CharField(model_attr='C003RZSC')

def index_queryset(self):
    return T031003.objects.all()

def prepare(self, obj):
    self.prepared_data = super(T031003Index, self).prepare(obj)
    self.prepared_data['text'] = obj.C003CHCD
    return self.prepared_data

site.register(T031003, T031003Index)

And the second one:

class T031002Index(RealTimeSearchIndex):
text = CharField(document=True, use_template=True)
C002USER = CharField(model_attr='C002USER')

def index_queryset(self):
    return T031002.objects.all()

def prepare(self, obj):
    self.prepared_data = super(T031002Index, self).prepare(obj)
    self.prepared_data['text'] = obj.C002USER
    return self.prepared_data
site.register(T031002, T031002Index)

And I have two template indexes for each of them:

T031003_text:

{{ object.C003INST }}
{{ object.C003CHCD }}
{{ object.C003MTR }}
{{ object.C003RZSC }}

T031002_text:

{{ object.C002USER }}
{{ object.C002INST }}

My template code:

{% if page.object_list %}    
{% for object in page.object_list %}
    <br>
    <li><font class="font">
      {{ object.C003RZSC }}, {{ object.C003INST }}, {{ object.C003CHCD }}, {{ object.C003MTR }}, {{ object.C002USER }}
    </li>
{% endfor %}

My view:

def search(req):
return SearchView(template='search.html')(req)

If I type in the search box a value from a field, let's say, that belongs to class T031002Index (like user = "vane"), it gives me the result:

"None, None, None, None, vane"

And, if I type a value from a field in class T031003Index, it gives me the result:

"pencil, 1, school material, general, None"

I have between these two classes in models.py a Foreign Key field, which is C002INST.

Could you guys give me an explanation? It seems easy, but I can't figure it out by myself.

Thanks in advance!

  • 1
    I was reading now the Haystack's index page and something caught my attention: "Meanwhile, work on 2.0.0-alpha has hit master, including the long-awaited addition of **multiple index support**. Similar to Django's multidb support, this will allow you to talk to multiple search engines at the same time. Things like master-slave setups, a separate engine for autocomplete or split public-facing/admin-only search are now trivial..." Is that it? I can't do what I plan in my question if Im not using 2.0 Haystack version? –  Jun 25 '12 at 20:42

1 Answers1

1

So, after a little help from close friends and a lot of research, I could find the solution.

1)I made an upgrade from Haystack 1.2.6 to Haystack 2.0.0

2)In my view, I changed the code to use AutoQuery and SearchQuerySet. It let's you use more that one word to search content and let's you filter results.

Here's the view:

def search(request):
sqs = SearchQuerySet().filter(content=AutoQuery(request.GET['q']))
return  render_to_response('search.html', {'sqs': sqs,})

4) Now, in "search_indexes.py", I changed the code to follow 2.0.0 version of Haystack and took off the "model_attr" from the foreign key (T031002Index, C002INST field).

Here's the code:

class T031003Index(RealTimeSearchIndex,Indexable):
   text = CharField(document=True, use_template=True)
   C003INST = IntegerField(model_attr='C003INST')
   C003CHCD = CharField(model_attr='C003CHCD')
   C003MTR = CharField(model_attr='C003MTR')
   C003RZSC = CharField(model_attr='C003RZSC')

def index_queryset(self):
    return T031003.objects.all()

def get_model(self):
    return T031003


class T031002Index(RealTimeSearchIndex,Indexable):
    text = CharField(document=True, use_template=True)
    C002INST = CharField()
    C002USER = CharField(model_attr='C002USER')

def index_queryset(self):
    return T031002.objects.all()

def get_model(self):
    return T031002

But even with all these changes, Haystack would iterate over the two indexes and would return null results. This is wrong and also would lead the user to confusion. So, I changed the template to show me the fields only when they have results which are not null:

{% if page.object_list %}    
{% for result in page.object_list %}
    {% if result.object.C003MTR%}
    <li><b>Matrícula:</b> {{ result.object.C003MTR }}</li>
    <li><b>CPF/CNPJ:</b> {{ result.object.C003CHCD }}</li>
    {% endif %}
    {% if result.object.C002INST %}
    <li><b>ID Instituição:</b> {{ result.object.C002INST }}</li>
    <li><b>Usuário:</b> {{ result.object.C002USER }}</li>
    {% endif %}
{%endfor%}

The "if" will do the trick to test if the field has null results.

Hope it helps other developers using Haystack with Django.