Highlight Index Search Results
-
When making a Full-Text Search query, in addition to retrieving documents that contain the searched terms, you can also request to get a list of text fragments that highlight the searched terms.
-
This article provides examples of highlighting search results when querying a static-index.
Prior to reading this article, please refer to Highlight search results for general knowledge about Highlighting and for dynamic-queries examples. -
To search and get fragments with highlighted terms when querying a static-index,
the index field on which you search must be configured for highlighting. See examples below. -
In this page:
Highlight results - Map index
Configure a Map index for highlighting:
To search and get fragments with highlighted terms,
the index-field on which you search must be configured as follows:
FieldStorage.YES
- store the field in the indexFieldIndexing.SEARCH
- allow Full-Text searchFieldTermVector.WITH_POSITIONS_AND_OFFSETS
- store the term's position and offsets
# Define a Map index:
# ===================
class Employees_ByNotes(AbstractIndexCreationTask):
# The IndexEntry defines index-field 'employee_notes'
class IndexEntry:
def __init__(self, employee_notes: str = None):
self.employee_notes = employee_notes
def __init__(self):
super().__init__()
self.map = "from employee in docs.Employees select new { employee_notes = employee.notes[0] }"
# Configure index-field 'employee_notes' for highlighting:
# ========================================================
self._store("employee_notes", FieldStorage.YES)
self._index("employees_notes", FieldIndexing.SEARCH)
self._term_vector("employee_notes", FieldTermVector.WITH_POSITIONS_AND_OFFSETS)
Query the index with search
:
# Define a callback function that takes Highlightings as an argument
# This function will be called by passing resulting Highlightings
def __highlight_callback(highlightings: Highlightings):
# Process the results here
highlightings.get_fragments(...)
...
employees_results = list(
session
# Query the map index
.query_index_type(Employees_ByNotes, Employees_ByNotes.IndexEntry)
# Search for documents containing the term 'manager'
.search("employee_notes", "manager")
# Request to highlight the searched term by calling 'highlight'
# Pass the callback function
.highlight("employee_notes", 35, 2, __highlight_callback).of_type(Employee)
)
from index "Employees/ByNotes"
where search(EmployeeNotes, "manager")
include highlight(EmployeeNotes, 35, 2)
Query the index with where_equals
:
manager_highlights: Optional[Highlightings] = None
# Define a callback function that takes Highlightings as an argument
# This function will be called by passing resulting Highlightings
def __manager_highlights_callback(highlightings: Highlightings):
# Process the results here or assign to nonlocal variable to access them later
# e.g. highlightings.get_fragments(...)
nonlocal manager_highlights
manager_highlights = highlightings
employees_results = list(
session
# Query the map index
.query_index_type(Employees_ByNotes, Employees_ByNotes.IndexEntry)
# Request to highlight the searched term by calling 'highlight'
.highlight("employees_notes", 35, 2, __manager_highlights_callback)
# Search for documents containing the term 'manager'
.where_equals("employee_notes", "manager").of_type(Employee)
)
from index "Employees/ByNotes"
where EmployeeNotes == "manager"
include highlight(EmployeeNotes, 35, 2)
Process results:
# 'employees_results' contains all Employee DOCUMENTS that contain the term 'manager'.
# 'manager_highlights' contains the text FRAGMENTS that highlight the 'manager' term.
builder = ["<ul>"]
for employee in employees_results:
# Call 'get_fragments' to get all fragments for the specified employee Id
fragments = manager_highlights.get_fragments(employee.Id)
for fragment in fragments:
builder.append(f"\n<li>Doc: {employee.Id}</li>")
builder.append(f"\n<li>Fragment: {fragment}</li>")
builder.append("\n<li></li>")
builder.append("\n</ul>")
fragments_html = "".join(builder)
# The resulting fragments_html:
# =============================
# <ul>
# <li>Doc: employees/2-A</li>
# <li>Fragment: to sales <b style="background:yellow">manager</b> in January</li>
# <li>Doc: employees/5-A</li>
# <li>Fragment: to sales <b style="background:yellow">manager</b> in March</li>
# <li></li>
# </ul>
Highlight results - Map-Reduce index
Configure a Map-Reduce index for highlighting:
To search and get fragments with highlighted terms in a Map-Reduce index:
-
The index-field on which you search must be configured with:
FieldStorage.YES
- store the field in the indexFieldIndexing.SEARCH
- allow Full-Text searchFieldTermVector.WITH_POSITIONS_AND_OFFSETS
- store the term's position and offsets
-
The index-field by which you group-by must configured with:
FieldStorage.YES
- store the field in the index
# Define a Map-Reduce index:
# ==========================
class ContactDetailsPerCountry(AbstractIndexCreationTask):
# The IndexEntry class defines the index-fields
class IndexEntry:
def __init__(self, country: str = None, contact_details: str = None):
self.country = country
self.contact_details = contact_details
def __init__(self):
super().__init__()
# The 'map' function defines what will be indexed from each document in the collection
self.map = "from company in docs.Companies select new { country = company.Address.Country, contact_details = company.Contact.Name + ' ' + company.Contact.Title }"
# The 'reduce' function specifies how data is grouped and aggregated
# Set 'country' as the group-by key
# 'contact_details' will be grouped per 'country'
# Specify the aggregation
# we'll use string.Join as the aggregation function
self.reduce = (
"from result in results group result by result.country into g select new { country = g.key, contact_details = string.Join("
", g.Select(x => x.contact_details) )}"
)
# Configure index-field 'country' for Highlighting:
# =================================================
self._store("country", FieldStorage.YES)
# Configure index-field 'contact_details' for Highlighting
self._store("contact_details", FieldStorage.YES)
self._index("contact_details", FieldIndexing.SEARCH)
self._term_vector("contact_details", FieldTermVector.WITH_POSITIONS_AND_OFFSETS)
Query the index:
# Define the key by which the resulting fragments are grouped:
# ============================================================
options = HighlightingOptions(
# Set 'group_key' to be the index's group-by key
# The resulting fragments will be grouped per 'country'
group_key="Country"
)
# Define a callback function that takes Highlightings as an argument:
# ===================================================================
agent_highlights: Optional[Highlightings] = None
def __agent_highlights_callback(highlightings: Highlightings):
# Process the results here or assign to nonlocal variable to access them later
nonlocal agent_highlights
agent_highlights = highlightings
# Query the map-reduce index:
# ===========================
details_per_country = list(
session.query_index_type(ContactDetailsPerCountry, ContactDetailsPerCountry.IndexEntry)
# Search for results containing the term 'agent'
.search("contact_details", "agent")
# Request to highlight the searched term by calling 'highlight'
# Pass the defined 'options'
.highlight("contact_details", 35, 2, __agent_highlights_callback, options)
)
from index "ContactDetailsPerCountry"
where search(ContactDetails, "agent")
include highlight(ContactDetails, 35, 2, $p0)
{"p0":{"GroupKey":"Country"}}
Process results:
# 'details_per_country' contains the contacts details grouped per country.
# 'agent_highlights' contains the text FRAGMENTS that highlight the 'agent' term.
builder = ["<ul>"]
for item in details_per_country:
# Call 'get_fragments' to get all fragments for the specified country key
fragments = agent_highlights.get_fragments(item.country)
for fragment in fragments:
builder.append(f"\n<li> Country: {item.country}</li>")
builder.append(f"\n<li> Fragment: {fragment}</li>")
builder.append(f"\n<li></li>")
builder.append("\n</ul>")
fragments_html = "".join(builder)
# The resulting fragmentsHtml:
# ============================
#
# <ul>
# <li>Country: UK</li>
# <li>Fragment: Devon Sales <b style="background:yellow">Agent</b> Helen Bennett</li>
# <li></li>
# <li>Country: France</li>
# <li>Fragment: Sales <b style="background:yellow">Agent</b> Carine Schmit</li>
# <li></li>
# <li>Country: France</li>
# <li>Fragment: Saveley Sales <b style="background:yellow">Agent</b> Paul Henriot</li>
# <li></li>
# <li>Country: Argentina</li>
# <li>Fragment: Simpson Sales <b style="background:yellow">Agent</b> Yvonne Moncad</li>
# <li></li>
# <li>Country: Argentina</li>
# <li>Fragment: Moncada Sales <b style="background:yellow">Agent</b> Sergio</li>
# <li></li>
# <li>Country: Brazil</li>
# <li>Fragment: Sales <b style="background:yellow">Agent</b> Anabela</li>
# <li></li>
# <li>Country: Belgium</li>
# <li>Fragment: Dewey Sales <b style="background:yellow">Agent</b> Pascale</li>
# <li></li>
# </ul>
Customize highlight tags
-
Default tags:
- Please refer to Highlight tags to learn about the default html tags used to wrap the highlighted terms.
-
Customizing tags:
-
The default html tags that wrap the highlighted terms can be customized to any other tags.
-
Customizing the wrapping tags when querying an index is done exactly the same as when making
a dynamic query where aHighlightingOptions
object is passed to theHighlight
method. -
Follow the example in Highlight - customize tags.
-