Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions solr/cores/conf/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,29 @@
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
</fieldType>


<fieldType name="spellcheck_text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>

<fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />

<!-- Define the new text field for queries -->
<field name="text" type="text_general" indexed="true" stored="true" multiValued="true"/>

<!-- Define the field for spellcheck -->
<field name="spellcheck" type="spellcheck_text" indexed="true" stored="false" multiValued="true"/>
<!-- Define the field for storing the thumbnail URL -->
<field name="thumbnail_url" type="string" stored="true" indexed="false" />

<!-- Copy field directives for aggregating values into the text field -->
<copyField source="wikidata_id_s" dest="text"/>
<copyField source="*_ss" dest="text" />
<copyField source="*_ss" dest="spellcheck"/>
</schema>
23 changes: 23 additions & 0 deletions solr/cores/conf/solrconfig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,16 @@
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>

<str name="spellcheck">true</str>
<str name="spellcheck.dictionary">default</str>
<str name="spellcheck.extendedResults">true</str>
<str name="spellcheck.collate">true</str>
</lst>

<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>

<!-- A request handler that returns indented JSON by default -->
Expand All @@ -84,6 +93,20 @@
<str name="df">text</str>
</lst>
</requestHandler>

<!-- SpellCheckComponent -->
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<lst name="spellchecker">
<str name="name">default</str>
<str name="field">spellcheck</str>
<str name="classname">solr.DirectSolrSpellChecker</str>
<int name="minQueryLength">3</int>
<float name="accuracy">0.3</float>
<int name="maxEdits">2</int>
<str name="distanceMeasure">internal</str>
</lst>
</searchComponent>

<initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell">
<lst name="defaults">
<str name="df">text</str>
Expand Down
68 changes: 53 additions & 15 deletions web-app/django/VIM/apps/instruments/views/instrument_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def get_context_data(self, **kwargs):
instruments,
has_other_pages,
facet_data,
effective_query,
) = self._paginate_solr_results(page_size)

# Add pagination data to context
Expand All @@ -163,6 +164,9 @@ def get_context_data(self, **kwargs):
context["hbs_facet"] = hbs_facet
context["search_query"] = search_query if search_query else None

# Add spellcheck suggestion to context
context["effective_query"] = effective_query

# Get contextual HBS facets (respects current search)
hbs_facet_list = self._get_contextual_hbs_facets(facet_data)
context["hbs_facets"] = hbs_facet_list
Expand Down Expand Up @@ -263,7 +267,7 @@ def _build_solr_query(self, language: Language, include_facets: bool = False):
def _get_solr_page_results(
self, solr, query_params: dict, page_size: int, start: int
):
"""Get a specific page of Solr search results with filter queries and total count."""
"""Get a specific page of Solr search results with consistent facets and spellcheck support."""
solr_params = {
**query_params,
"rows": page_size,
Expand All @@ -272,20 +276,44 @@ def _get_solr_page_results(
# Remove our custom params
lang_code = solr_params.pop("lang_code")

solr_response = solr.search(**solr_params)
effective_query = solr_params.get("q")
solr_params["spellcheck.q"] = effective_query

# Execute initial query
response = solr.search(**solr_params)

# Attempt spellcheck if no results
if response.hits == 0:
raw = response.raw_response
spellcheck = raw.get("spellcheck", {})
collations = spellcheck.get("collations", [])
if len(collations) >= 2:
spellcheck_suggestion = collations[1]

corrected_params = solr_params.copy()
corrected_params["q"] = spellcheck_suggestion

corrected_response = solr.search(**corrected_params)

if corrected_response.hits > 0:
response = corrected_response
effective_query = spellcheck_suggestion

instruments = [
SolrInstrument(doc, lang_code=lang_code) for doc in solr_response.docs
SolrInstrument(doc, lang_code=lang_code) for doc in response.docs
]
total_count = solr_response.hits # pysolr's hits corresponds to Solr's numFound
total_count = response.hits

# Return facet data if available
facet_data = None
if hasattr(solr_response, "facets") and solr_response.facets:
facet_data = solr_response.facets.get("facet_pivot", {}).get(
"hbs_prim_cat_s,hbs_prim_cat_label_s", []
)
facet_data = response.facets.get("facet_pivot", {}).get(
"hbs_prim_cat_s,hbs_prim_cat_label_s", []
)

return instruments, total_count, facet_data
return (
instruments,
total_count,
facet_data,
effective_query,
)

def _get_contextual_hbs_facets(self, contextual_facet_data):
"""Get HBS facets showing all categories with contextual counts (including zero)."""
Expand Down Expand Up @@ -358,15 +386,25 @@ def _paginate_solr_results(self, page_size):
query_params = self._build_solr_query(language, include_facets=True)

# Get page results, total count, and facet data in one query
page_results, total_count, facet_data = self._get_solr_page_results(
solr, query_params, page_size, start
)
(
page_results,
total_count,
facet_data,
effective_query,
) = self._get_solr_page_results(solr, query_params, page_size, start)

# Create paginator and page objects
paginator = SolrPaginator(page_results, page_size, total_count)
page = Page(page_results, page_number, paginator)

return (paginator, page, page_results, page.has_other_pages(), facet_data)
return (
paginator,
page,
page_results,
page.has_other_pages(),
facet_data,
effective_query,
)

def get(self, request, *args, **kwargs):
language_en = request.GET.get("language", None)
Expand Down
26 changes: 21 additions & 5 deletions web-app/django/VIM/templates/instruments/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,27 @@ <h4 class="ms-3 me-2 my-auto">
<span id="instrumentNum"
data-instrument-num="{{ page_obj.paginator.count }}"
class="text-start">
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} entries
{% if hbs_facet_name %}for{% endif %}
<strong>{{ hbs_facet_name }}</strong>
{% if search_query %}
for search query "<strong class="notranslate">{{ search_query }}</strong>"
<!-- Case: no results -->
{% if page_obj.paginator.count == 0 %}
No results found
{% if hbs_facet_name %}for <strong>{{ hbs_facet_name }}</strong>{% endif %}
{% if search_query %}
for search query <strong class="notranslate">"{{ search_query }}"</strong>.
{% endif %}
<!-- Case: results with a spellcheck suggestion -->
{% elif effective_query != search_query %}
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }}
{% if hbs_facet_name %}for <strong>{{ hbs_facet_name }}</strong>{% endif %}
{% if search_query %}
for search query <strong class="notranslate">"{{ effective_query }}"</strong>, as no results were found for <span class="notranslate">"{{ search_query }}"</span>.
{% endif %}
<!-- Case: results for the original search query -->
{% else %}
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }}
{% if hbs_facet_name %}for <strong>{{ hbs_facet_name }}</strong>{% endif %}
{% if search_query %}
for search query <strong class="notranslate">"{{ search_query }}"</strong>.
{% endif %}
{% endif %}
</span>
</div>
Expand Down
Loading