Highlight Search Results
-
When making a Full-Text Search query,
in addition to retrieving documents that contain the searched terms in the results,
you can also request to get a list of text fragments that highlight the searched terms. -
The highlighted terms can enhance user experience when searching for documents with specific content.
-
This article shows highlighting search results when making a dynamic-query.
For highlighting search results when querying a static-index see highlight index search results.
Highlight - basic example
# Make a full-text search dynamic query:
# ======================================
# Define a callback that takes highlightings as an argument
sales_highlightings: Optional[Highlightings] = None
def _sales_highlights(highlightings: Highlightings):
# You may use the results (highlightings) here in any way desired
sales_highlightings = highlightings
employees_result = list( # Execute the query inside the parenthesis
session
# Make a query on 'Employees' collection
.query(object_type=Employee)
# Search for documents containing the term 'sales' in their 'Notes' field
.search("Notes", "sales")
# Request to highlight the searched term by calling 'Highlight'
.highlight(
"Notes", # The document-field name in which we search
35, # Max length of each text fragment
4, # Max number of fragments to return per document
_sales_highlights, # An out param for getting the highlighted text fragments
)
)
from "Employees"
where search(Notes, "sales")
include highlight(Notes, 35, 4)
# Process results:
# ================
# 'employees_results' contains all Employee DOCUMENTS that have 'sales' in their 'Notes' field.
# 'sales_highlights' contains the text FRAGMENTS that highlight the 'sales' term.
builder = ["<ul>", {os.linesep}]
for employee in employees_result:
# Call 'get_fragments' to get all fragments for the specified employee Id
fragments = sales_highlightings.get_fragments(employee.Id)
for fragment in fragments:
builder.append(f"{os.linesep}<li>Doc: {employee.Id} Fragment: {fragment}</li>")
fragments_html = builder.append(f"{os.linesep}</ul>")
# The resulting fragments_html:
# ============================
# <ul>
# <li>Doc: employees/2-A Fragment: company as a <b style="background:yellow">sales</b></li>
# <li>Doc: employees/2-A Fragment: promoted to <b style="background:yellow">sales</b> manager in</li>
# <li>Doc: employees/2-A Fragment: president of <b style="background:yellow">sales</b> in March 1993</li>
# <li>Doc: employees/2-A Fragment: member of the <b style="background:yellow">Sales</b> Management</li>
# <li>Doc: employees/3-A Fragment: hired as a <b style="background:yellow">sales</b> associate in</li>
# <li>Doc: employees/3-A Fragment: promoted to <b style="background:yellow">sales</b> representativ</li>
# <li>Doc: employees/5-A Fragment: company as a <b style="background:yellow">sales</b> representativ</li>
# <li>Doc: employees/5-A Fragment: promoted to <b style="background:yellow">sales</b> manager in</li>
# <li>Doc: employees/5-A Fragment: <b style="background:yellow">Sales</b> Management." </li>
# <li>Doc: employees/6-A Fragment: for the <b style="background:yellow">Sales</b> Professional.</li>
# </ul>
Highlight tags
-
By default, the highlighted term is wrapped with the following html:
<b style="background:yellow">term</b>
-
When requesting to highlight multiple terms,
the background color returned for each different term will be in the following order:- yellow,
- lawngreen,
- aquamarine,
- magenta,
- palegreen,
- coral,
- wheat,
- khaki,
- lime,
- deepskyblue,
- deeppink,
- salmon,
- peachpuff,
- violet,
- mediumpurple,
- palegoldenrod,
- darkkhaki,
- springgreen,
- turquoise,
- powderblue
-
The html tags that wrap the highlighted terms can be customized to any other tags.
See customize tags below.
Highlight results in Studio
View highlighted fragments in the Query View
-
Auto-Index
This is the auto-index that was created by the server to serve the dynamic-query. -
Results tab
The results tab contains the resulting documents that match the provided RQL query. -
Highlight tab
The highlight tab shows the resulting fragments that were included in the query result.
Highlight - customize tags
- The html tags that wrap the highlighted terms can be customized to any other tags.
# Define customized tags to use for highlighting the searched terms
# =================================================================
tags_to_use = HighlightingOptions(
# Provide strings of your choice to 'PreTags' & 'PostTags', e.g.:
# the first term searched for will be wrapped with '+++'
# the second term searched for will be wrapped with '<<<' & '>>>'
pre_tags=["+++", "<<<"],
post_tags=["+++", ">>>"],
)
# Define a callback that takes highlightings as an argument
manager_highlightings: Optional[Highlightings] = None
def _manager_highlights(highlightings: Highlightings):
# You may use the results (highlightings) here in any way desired
manager_highlightings = highlightings
# Make a full-text search dynamic query:
# ======================================
employees_result = list(
session.query(object_type=Employee)
# Search for:
# * documents containing the term 'sales' in their 'Notes' field
# * OR for documents containing the term 'manager' in their 'Title' field
.search("Notes", "sales")
.search("Title", "manager")
# Call 'Highlight' for each field searched
# Pass 'tagsToUse' to OVERRIDE the default tags used
.highlight("Notes", 35, 1, _sales_highlights)
.highlight("Title", 35, 1, tags_to_use, _manager_highlights)
)
from "Employees"
where (search(Notes, "sales") or search(Title, "manager"))
include highlight(Notes, 35, 1, $p0), highlight(Title, 35, 1, $p1)
{
"p0":{"PreTags":["+++","<<<"],"PostTags":["+++",">>>"]},
"p1":{"PreTags":["+++","<<<"],"PostTags":["+++",">>>"]}
}
# The resulting salesHighlights fragments:
# ========================================
#
# "for the +++Sales+++ Professional."
# "hired as a +++sales+++ associate in"
# "company as a +++sales+++"
# "company as a +++sales+++ representative"
#
# The resulting managerHighlights fragments:
# ==========================================
#
# "Sales <<<Manager>>>"
Highlight - projected results
- Highlighting can also be used when projecting query results.
# Make a full-text search dynamic query & project results:
# ========================================================
# Define a callback that takes highlightings as an argument
terms_highlightings: Optional[Highlightings] = None
def _terms_highlights(highlightings: Highlightings):
# You may use the results (highlightings) here in any way desired
terms_highlightings = highlightings
employees_projected = list(
session.query(object_type=Employee)
.search("Notes", "manager german")
.highlight("Notes", 35, 2, _terms_highlights)
.select_fields_query_data(
QueryData.custom_function("o", "{ Name: o.FirstName + ' ' + o.LastName, Title: o.Title }"),
)
)
# todo reeb & gracjan: lets implement it after 5.4 release
# i have a perfect ticket for that
# https://issues.hibernatingrhinos.com/issue/RDBC-820#focus=Comments-67-1050834.0-0
from "Employees" as x
where search(x.Notes, "manager german")
select { Name : "{0} {1}".format(x.FirstName, x.LastName), Title : x.Title }
include highlight(Notes, 35, 2)
# The resulting fragments from termsHighlights:
# =============================================
#
# "to sales <b style=\"background:yellow\">manager</b> in March"
# "and reads <b style=\"background:lawngreen\">German</b>. He joined"
# "to sales <b style=\"background:yellow\">manager</b> in January"
# "in French and <b style=\"background:lawngreen\">German</b>."
#
# NOTE: each search term is wrapped with a different color
# 'manager' is wrapped with yellow
# 'german' is wrapped with lawngreen
Syntax
def highlight(
self,
field_name: str,
fragment_length: int,
fragment_count: int,
highlightings_callback: Callable[[Highlightings], None],
options: Optional[HighlightingOptions] = None,
) -> DocumentQuery[_T]: ...
Parameter | Type | Description |
---|---|---|
field_name | str |
Name of the field that contains the searched terms to highlight |
fragment_length | int |
Maximum length of a text fragment Must be >= 18 |
fragment_count | int |
Maximum number of text fragments that will be returned |
highlightings_callback | Callable[[Highlightings], None] |
A callback function to retrieve the highlighted text fragments for each returned result |
options (Optional) | HighlightingOptions |
Customizing options |
Highlighting options:
def __init__(self, group_key: str = None, pre_tags: List[str] = None, post_tags: List[str] = None):
self.group_key = group_key
self.pre_tags = pre_tags
self.post_tags = post_tags
Option | Type | Description |
---|---|---|
group_key | str |
Grouping key for the results. Used when highlighting query results from a Map-Reduce index. If None results are grouped by document ID (default).Note: Highlighting is Not available for dynamic aggregation queries. |
pre_tags | List[str] |
Array of PRE tags used to wrap the highlighted search terms in the text fragments. |
post_tags | List[str] |
Array of POST tags used to wrap the highlighted search terms in the text fragments. |
Highlightings object:
def __init__(self, field_name: str):
self.field_name = field_name
...
@property
def result_indents(self) -> Set[str]: ...
Property | Type | Description |
---|---|---|
field_name | str |
Name of the field that contains the searched terms to highlight |
result_indents | Set[str] |
The resulting keys (document IDs, or the map-reduce keys) |
def get_fragments(self, key: str) -> List[str]: ...
Method | Return Type | Description |
---|---|---|
get_fragments | List[str] |
Returns the list of the highlighted text fragments for the passed document ID, or the map-reduce key |