Translator
Translators convert between:
Generic query syntax used in internal logic, and
Specific query syntax required by a given search engine (e.g., PubMed, EBSCO, Web of Science).
Each translator implements QueryTranslator, the abstract base class from translator_base.py
.
Translator responsibilities
A translator must implement the following two class methods:
to_generic_syntax(query, *, field_general) -> Query
to_specific_syntax(query) -> Query
Each method receives a Query object (the internal AST) and must return a new Query object with appropriately translated search fields and structure.
Versioned translators
Translators are organized in versioned modules such as
search_query/pubmed/v1/translator.py
. See
versioning policy for details.
This structure preserves older versions,
enabling reproducible translations and ensuring backward compatibility.
A central registry in search_query.translator
provides a TRANSLATORS
mapping,
which dynamically selects the appropriate translator version at runtime. Invoking
translate(..., translator_version="latest")
loads the most recent version for the
specified platform.
To introduce a new translator version, duplicate the previous versioned directory,
update the implementation as needed, and register the new version in the TRANSLATORS
dictionary.
Utility methods provided
The base class (QueryTranslator) provides the following utilities:
move_field_from_operator_to_terms(query)
: Moves a shared search field from the operator level to each child query.flatten_nested_operators(query)
: Merges nested logical operators of the same type into a flat structure.move_fields_to_operator(query)
: If all children have the same field, moves it to the parent node.
Search field mapping
Field mapping is expected to be defined in a constants_<source>.py file and typically includes:
syntax_str_to_generic_field_set()
: maps specific syntax string (e.g., TI, AB) to set of generic `Fields`. When the set contains multiple elements, the query must be extended with OR (see PubMed translator:_expand_combined_fields()
).generic_field_to_syntax_field()
: maps generic Fields to platform-specific syntax (set of fields). When combined fields are available, the query must be adapted before (see PubMed tranlsator:_combine_tiab()
).
Each translator should:
Translate fields in both directions
Handle combined fields (e.g., [tiab] in PubMed)
Optionally restructure the query for consistency
Code skeleton
from search_query.constants_example import generic_field_set_to_syntax_set
from search_query.constants_example import map_field
from search_query.query import Query
from search_query.translator_base import QueryTranslator
class CustomTranslator(QueryTranslator):
"""Translator for Custom queries."""
@classmethod
def to_generic_syntax(cls, query: Query, *, field_general: str) -> Query:
query = query.copy()
cls.translate_fields_to_generic(query)
return query
@classmethod
def to_specific_syntax(cls, query: Query) -> Query:
query = query.copy()
cls._translate_fields(query)
return query
@classmethod
def translate_fields_to_generic(cls, query: Query) -> None:
if query.field:
fields = map_field(query.field.value)
if len(fields) == 1:
query.field.value = fields.pop()
else:
raise NotImplementedError
for child in query.children:
cls.translate_fields_to_generic(child)
@classmethod
def _translate_fields(cls, query: Query) -> None:
if query.field:
specific = generic_field_to_syntax_field(query.field.value)
query.field.value = specific
for child in query.children:
cls._translate_fields(child)
Advanced features
Some translators include advanced restructuring logic:
PubMed: supports [tiab] expansion into OR combinations of [ti] and [ab]