Warning |
---|
This functionality is only applicable when building a QPL query manually, if you want custom operators for the parser, you will need to generate a new grammar in which case, please contact the development team |
PyQPL allows to include custom operators in your query and even add translation for these. There are 2 ways to make use of a custom operator, besides the translation process, one quick and simple and another one defining the operator with a class.
For both methods we need to make use of manual operator function (op)
Code Block | ||||
---|---|---|---|---|
| ||||
qpl.op(type_='MY_OPERATOR', operands='one', fields=['title'], boost=1.0) |
This method only consist on using the manual operator function (op), and adding the custom operator as the type, in this example GEO
Code Block |
---|
qpl = QPL(options=options)
qpl_query = qpl.and_(operands=[
qpl.or_(operands=[
qpl.phrase('San Jose'),
qpl.phrase('Costa Rica'),
qpl.not_(qpl.phrase('California'))
]),
qpl.op(type_='geo', operands=['9°54\'52.5"N', '84°05\'15.5"W'], fields='geo_point', boost=6)
])
print(qpl_query) |
The resulting qpl query will give this
Code Block |
---|
and(or(phrase(San Jose),phrase(Costa Rica),not(phrase(California))),geo_point:geo(9°54'52.5"N,84°05'15.5"W)^6) |
Note |
---|
From the important part is to know the operands(parameters) provided to the the function, since they could be anything we need to be extra careful when doing the translation |
Custom Class Operator
This method is a more formal way to define the custom operator since it relays on a class to process, manipulate and optimize the query
The custom operator inherits from Operator Class, there for you can choose what to overwrite in order to fit your needs
Code Block |
---|
class GeoOP(Operator): def add_operand(self, operand: OperatorOrStr): op = operand if isinstance(operand, str): # I know this is not how you translate coordinates, so shhh op = operand.strip().replace('\'', '').replace('"', '').replace('.', '') if op.endswith('N') or op.endswith('n') or op.endswith('E') or op.endswith('E'): pass elif op.endswith('S') or op.endswith('S') or op.endswith('W') or op.endswith('W'): # we add the minus for this coordenates op = '-' + op # Remove the last letter op = op[:-1] op = op.replace('°', '.') super().add_operand(op) def _optimize(self): super()._optimize() |
Code Block |
---|
options = QPLOptions(fields='content', custom_operators={ 'geo': GeoOP }) qpl = QPL |
(options=options)
qpl_query = qpl.and_(operands=[
qpl.or_(operands=[
qpl.phrase('San Jose'),
qpl.phrase('Costa Rica'),
qpl.not_(qpl.phrase('California'))
]),
qpl.op(type_='geo', operands=['9°54\'52.5"N', '84°05\'15.5"W'], fields='geo_poit', boost=6)
])
print(qpl_query) |
Code Block |
---|
and(or(phrase(San Jose),phrase(Costa Rica),not(phrase(California))),geo_poit:geo(9.54525,-84.05155)^6) |