YAQL - Yet Another Query Language
YAQL (Yet Another Query Language) is an embeddable and extensible Python query language designed to perform complex queries against arbitrary objects. It features a comprehensive standard library of querying functions and supports user-defined extensions. The current version is 3.2.0, actively maintained with infrequent releases, and it is distributed via PyPI.
Common errors
-
YaqlEvaluationException: Unable to evaluate expression ''$.data.distinct()''. TypeError: unhashable type: 'dict'
cause Attempting to use `distinct()` on a collection containing unhashable types, such as dictionaries, in older versions of YAQL where this was a known bug.fixEnsure you are using YAQL version 3.2.0 or higher. If the problem persists with custom types, ensure that objects intended for `distinct()` or similar set-like operations implement `__hash__` and `__eq__` methods correctly. -
NameError: name 'yaql' is not defined
cause The `yaql` module was not imported before attempting to use its functions or factory. This commonly happens if trying to use `yaql.factory.YaqlFactory()` without `import yaql` or `from yaql.factory import YaqlFactory`.fixAdd `import yaql` at the top of your Python script or `from yaql.factory import YaqlFactory` if directly accessing the factory. -
SyntaxError: invalid syntax (in YAQL expression)
cause The YAQL expression string contains syntax errors, such as unmatched quotes, incorrect operators, or invalid function calls according to YAQL's grammar. This is particularly common when transitioning from other query languages or not fully understanding YAQL's specific syntax for variable access (`$`), function calls, and operators.fixCarefully review the YAQL expression against the official YAQL language reference documentation. Pay attention to variable access (`$variable` or `$`), string literal quoting (single or double quotes), and correct operator usage. Debug by evaluating smaller parts of the expression or by using the YAQL REPL tool.
Warnings
- gotcha YAQL is designed to keep input data unchanged. Functions that appear to modify data actually return an updated copy, preserving the original data. This design also contributes to its thread-safety. Directly modifying input data structures from within YAQL functions can lead to unexpected behavior.
- gotcha There is no built-in syntax in YAQL to explicitly check if a variable exists versus being set to `null`. If a variable is not provided, it is implicitly assumed to be `null` when accessed. This can lead to ambiguity if you need to differentiate between a variable that doesn't exist and one that explicitly holds a `null` value.
- breaking Older versions of YAQL could raise a `YaqlEvaluationException: TypeError: unhashable type: 'dict'` when using methods like `distinct()` on an array of dictionaries. This was a bug related to how YAQL handled dictionary hashing within certain operations.
Install
-
pip install yaql
Imports
- YaqlFactory
import yaql.factory.YaqlFactory
from yaql.factory import YaqlFactory
- yaql
import yaql
Quickstart
import yaql
from yaql.factory import YaqlFactory
data_source = {
'customers': [
{'name': 'John Doe', 'age': 30, 'city': 'New York', 'orders': [{'id': 1, 'amount': 100}, {'id': 2, 'amount': 250}]},
{'name': 'Jane Smith', 'age': 24, 'city': 'London', 'orders': [{'id': 3, 'amount': 150}]},
{'name': 'Peter Jones', 'age': 35, 'city': 'New York', 'orders': []}
]
}
# Create a YAQL engine
engine = YaqlFactory().create()
# Evaluate an expression to find customers in New York
expression = '$.customers.where($.city = "New York")'
result = engine(expression)(data=data_source)
print(f"Customers in New York: {list(result)}")
# Evaluate an expression to get names of customers with orders
expression_with_orders = '$.customers.where($.orders.len() >= 1).select($.name)'
result_with_orders = engine(expression_with_orders)(data=data_source)
print(f"Customers with orders: {list(result_with_orders)}")