Expressions¶
Expressions in ParadeDB Django define how search, filtering, and ranking logic is constructed in Django ORM queries. They translate your filters into ParadeDB-compatible queries for full-text or structured search.
⚠ Note on Parameters
key_field(str | KeyField), defaultid. see KeyField): The primary field used as the key for the operation.when using the
KeyFieldon related table (fk,o2o,m2m), make sure the join is applied using select_related or using reverse related query.
match_op(bool, defaultFalse): WhenTrue, the expression<key_field_or_lhs> @@@ actual_function()will be applied. WhenFalse(or not provided), only the function will be used to generate the SQL, and no key field match operation is applied.when
expression.fieldis amodels.ForTableFieldthen, in this casekey_fieldparamter is not required it will be automatically resolved and will set to the corresponding table model(table). make sure the join is applied when using a foreign fieldex(models.F(user__id)).
output_fieldcan be passed in the expression in case of custom field type. by default no need to pass output field.legacy: boolwhenTruethenparadedbschema functions will be used insteadpdb. no need to pass unless you want to use legacy function. see legacy settings
- All the Expressions is inside the
paradedb.expressionsmodule
ParadeOp¶
ParadeOp:
phrase = "###"
match = "|||"
match_conjunction = "&&&"
term = "==="
All¶
All( key_field: KeyField | str | models.F | TableField = "id", match_op: bool = False)
To learn more, see the ParadeDB All
Empty¶
Empty(key_field: KeyField | str | models.F | TableField = "id", match_op: bool = False)
To learn more, see the ParadeDB Empty.
Example
Search¶
Search(
field: str | models.F | TableField,
value: str | ValueCast| ParadeDbFunctionExpression,
escaped: bool = False,
op: typing.Literal["@@@", "|||", "===", "###", "&&&"] = "@@@"
)
- See TableField
@@@is default normal paradedb operator and evaluates complex query expressions like proximity searches, regex patterns, and parsed queries|||performs disjunctive matching, finding documents that contain any of the query term.###enforces both term presence and positional requirements, perfect for phrase matching&&&requires all terms to be present (conjunction)===performs exact token matching, ideal for categorical fields or identifier lookups|||, ===, &&&, ###, paradedb.cast.ValueCastonly supoorted in paradedb v2 api.
To learn more, see the ParadeDB Search Overview.
Example
Article.objects.filter(Search(field="title", value="well", escaped=False))
# using F.. when using on related field make sure join is applied using select_related
Article.objects.filter(Search(models.F("title"), "python"))
# using table field
Article.objects.filter(Search(TableField('title', key_field=KeyField(Article)), "python"))
# using search value with tokenizer. -- supported in v2 only
from paradedb.cast import ValueCast
Article.objects.filter(Search('title', ValueCast('django', 'pdb.ngram(1,2)')))
Match¶
Match(
field: str | models.F | TableField,
value: str,
distance: int = 0,
conjunction_mode: bool = False,
tokenizer: typing.Optional[
Tokenizer | typing.Optional[
typing.Literal[
"whitespace",
"keyword",
"ngram",
"regex",
"icu",
"jieba",
"chinese_lindera",
"chinese_compatible",
"source_code",
"raw",
]
]
] = None,
transposition_cost_one: str = True,
prefix: bool = False,
escaped: bool = False,
key_field: KeyField | str = "id",
match_op: bool = False
)
tokenizer: currently string tokenizers are supported. Tokenizer instance implementation will be available soon.
To learn more, see the ParadeDB Match.
Example
Article.objects.filter(
Match(
field="title",
value="python",
distance=1,
conjunction_mode=False,
prefix=True,
tokenizer="whitespace",
match_op=True,
)
)
Exists¶
Exists(field: str | models.F | TableField, key_field: KeyField | str = "id", match_op: bool = False)
To learn more, see the ParadeDB Exists.
Example
Article.objects.filter(Exists(field="rank", match_op=True))
Range¶
Range(
field: str | models.F | TableField,
range_type: typing.Literal["int4range", "int8range", "daterange", "tsrange", "tstzrange"],
start: int | str | datetime.datetime | datetime.date,
end: typing.Optional[int | str | datetime.datetime | datetime.date] = None,
bounds: typing.Literal["[)", "(]", "[]", "()"] = Range.RangeBound.INCLUSIVE_LOWER_EXCLUSIVE_UPPER,
key_field: KeyField | str = "id",
match_op: bool = False,
)
RangeType¶
RangeType.INT4RANGE # "int4range"
RangeType.INT8RANGE # "int8range"
RangeType.DATERANGE # "daterange"
RangeType.TSRANGE # "tsrange"
RangeType.TSTZRANGE # "tstzrange"
RangeBound¶
RangeBound.INCLUSIVE_LOWER_EXCLUSIVE_UPPER # "[)"
RangeBound.EXCLUSIVE_LOWER_INCLUSIVE_UPPER # "(]"
RangeBound.INCLUSIVE_BOTH # "[]"
RangeBound.EXCLUSIVE_BOTH # "()"
To learn more, see the ParadeDB Range.
Example
# Range Date
Article.objects.filter(
Range(
field="created",
range_type="daterange",
start=date(2025, 9, 2),
end=date(2025, 9, 10),
bounds="[)",
match_op=True,
)
)
# Range Integer
Article.objects.filter(
Range(
field="rank",
range_type="int4range", # Range.RangeType.INT4RANGE
start=1,
end=3,
bounds="()",
match_op=True,
)
)
# Unbounded Range
Article.objects.filter(
Range(
field="rank",
range_type="int4range", # Range.RangeType.INT4RANGE
start=1,
match_op=True,
)
)
RangeTerm¶
RangeTerm(
field: str | models.F | TableField,
term_or_range: str | int | float,
cast: typing.Literal[
"tsrange",
"int4range",
"int8range",
"daterange",
"tstzrange",
"bigint",
"date",
"double precision",
"integer",
"numeric",
"real",
"smallint",
'"char"',
"timestamp with time zone",
"timestamp without time zone",
"numrange",
],
relation: typing.Optional[typing.Literal["Intersects", "Within", "Contains"]] = None,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB RangeTerm.
Example
# Range Term With Date Range Fields
Article.objects.filter(
RangeTerm(
field="date_range",
term_or_range="'[2025-09-02,2025-09-10]'",
cast=Range.RangeType.DATERANGE,
relation=RangeTerm.Relation.Intersects,
match_op=True,
)
)
# Range with Integer Range Fields
Article.objects.filter(
RangeTerm(
field="price_range",
term_or_range=1,
cast=RangeTerm.Cast.integer,
match_op=True,
)
)
Regex¶
Regex(
field: str | models.F | TableField,
value: str,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB Regex.
Example
Article.objects.filter(
Regex(
field="title",
value='^well$',
match_op=True,
)
)
Term¶
Term(
field: str | models.F | TableField,
value: str,
enum_cast_field: typing.Optional[str] = None, # PostgreSQL cast type, e.g., 'int', 'date', 'timestamp'
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB Term.
Example
Article.objects.filter(Term(field="rank", value=100, match_op=True))
TermSet¶
TermSet(
terms: typing.List[Term],
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB TermSet.
Example
Article.objects.filter(
TermSet(
terms=[
Term(field="rank", value=1),
Term(field="rank", value=200),
],
match_op=True
)
)
FuzzyTerm¶
FuzzyTerm(
field: str | models.F | TableField,
value: str,
distance: int = 2,
transposition_cost_one: bool = True,
prefix: bool = False,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB FuzzyTerm.
Example
Article.objects.filter(
FuzzyTerm(
field="title",
value="well",
distance=2,
prefix=False,
transposition_cost_one=True,
match_op=True
)
)
Phrase¶
Phrase(
field: str | models.F | TableField,
pharses: typing.List[str] # must be atleast 2,
slop: int = 0,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB Phrase.
Example
Article.objects.filter(
Phrase(field="description", pharses=["quick", "brown", "fox"], slop=3, match_op=True)
)
PhrasePrefix¶
PhrasePrefix(
field: str | models.F | TableField,
pharses: typing.List[str], # must be atleast 2,
max_expansion: int = 0,
key_field: KeyField | str = "id",
match_op: bool = False
)
To learn more, see the ParadeDB PhrasePrefix.
Example
Article.objects.filter(
PhrasePrefix(field="title", pharses=["deep", "learn"], max_expansion=5, match_op=True)
)
ConstScore¶
ConstScore(
score: float | int,
query: ParadeDbFunctionExpression,
key_field: KeyField | str = "id",
match_op: bool = False
)
To learn more, see the ParadeDB ConstScore.
Example
Article.objects.filter(
Boolean(
should=[Term("title", value="running"), ConstScore(1.0, Match(field="title", value="shoes"))],
match_op=True,
)
)
Bm25Score¶
Bm25Score(key_field: KeyField | str | models.F | TableField = "id")
To learn more, see the ParadeDB BM25 Scoring.
Example
Article.objects.annotate(score=Bm25Score()).filter(score__gt=0).order_by("-score")
Boost¶
Boost(
factor: float | int,
query: ParadeDbFunctionExpression,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB Boost.
Example
Article.objects.filter(
Boolean(
should=[Term("title", value="running"), Boost(1.0, Match(field="title", value="shoes"))],
match_op=True,
)
)
DisjunctionMax¶
DisjunctionMax(
disjuncts: typing.List[ParadeDbFunctionExpression],
tie_breaker: int = 0,
key_field: KeyField | str = "id",
match_op: bool = False
)
To learn more, see the ParadeDB DisjunctionMax.
Example
Article.objects.filter(
DisjunctionMax(
disjuncts=[Term(field="title", value="running"), Term(field="title", value="shoes")],
tie_breaker=1,
match_op=True,
)
)
Boolean¶
Boolean(
must: typing.Optional[typing.List[ParadeDbFunctionExpression]] = None,
must_not: typing.Optional[typing.List[ParadeDbFunctionExpression]] = None,
should: typing.Optional[typing.List[ParadeDbFunctionExpression]] = None,
key_field: KeyField | str = "id",
match_op: bool = False
)
To learn more, see the ParadeDB Boolean.
Example
Article.objects.filter(
Boolean(
must=[Match(field="title", value="python")],
must_not=[Match("description", value="python", tokenizer="raw")],
should=[Term("title", value="python"), ConstScore(1.0, Term("title", value="python"))],
match_op=True,
)
)
Snippet¶
Snippet(
field: str | models.F | TableField,
limit: typing.Optional[int] = None,
offset: typing.Optional[int] = None,
start_tag: typing.Optional[str] = None,
end_tag: typing.Optional[str] = None,
max_num_chars: typing.Optional[int] = None
)
To learn more, see the ParadeDB Snippet and Highlighting.
Example
Article.objects.annotate(
snippet_title=Snippet(field="description", start_tag="<b>", end_tag="</b>", max_num_chars=100),
snippet_description=Snippet(field="description", start_tag="<b>", end_tag="</b>", max_num_chars=100),
).filter(
Boolean(must=[Match(field="title", value="hello")], match_op=True)
| Match(field="description", value="well", match_op=True)
)
MoreLikeThis¶
MoreLikeThis(
document_id: typing.Optional[str | int] = None,
document: typing.Optional[dict] = None,
fields: typing.Optional[typing.List[str]] = None,
min_doc_frequency: typing.Optional[int] = None,
max_doc_frequency: typing.Optional[int] = None,
min_term_frequency: typing.Optional[int] = None,
max_query_terms: typing.Optional[int] = None,
min_word_length: typing.Optional[int] = None,
max_word_length: typing.Optional[int] = None,
boost_factor: typing.Optional[int | float] = None,
stop_words: typing.Optional[typing.List[str]] = None,
key_field: KeyField | str = "id",
match_op: bool = False,
)
⚠ Note: -
document_idanddocumentcannot be used together. Whendocumentis provided, thedocument_idfield will be excluded, and vice versa. -document_idandfieldscan be used together, whiledocumentmust be used alone.
To learn more, see the ParadeDB MoreLikeThis.
Example
# with document id and field
Article.objects.filter(
MoreLikeThis(
document_id=1,
fields=["title", "description"],
min_term_frequency=1,
max_query_terms=20,
match_op=True
)
)
# with document field
Article.objects.filter(
MoreLikeThis(
document={"title": "well", "description": "world"},
min_term_frequency=1,
max_query_terms=20,
match_op=True
)
)
Parse¶
Parse(
query: str,
lenient: bool = False,
conjunction_mode: bool = False,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB Parse.
Example
Article.objects.filter(
Parse(
query="title:well AND description:well",
lenient=True,
conjunction_mode=True,
key_field="id",
match_op=True,
)
)
ParseWithField¶
ParseWithField(
field: str | models.F | TableField,
value: str,
lenient: bool = False,
conjunction_mode: bool = False,
key_field: KeyField | str = "id",
match_op: bool = False,
)
To learn more, see the ParadeDB ParseWithField.
Example
Article.objects.filter(
ParseWithField(
field="title",
value="well",
lenient=True,
conjunction_mode=True,
match_op=True,
)
& ParseWithField(field="description", value="hello", conjunction_mode=True, match_op=True)
)
Proximity¶
Proximity(
values: typing.List[str | int | ProximityRegex | ProximityArray | typing.Literal["##", "##>"]],
field: typing.Optional[str | models.F | TableField] = None,
)
valuesexpected length must be >= 3. passing wrong sequence value will raiseValueError.
To learn more, see the ParadeDB Proximity.
Example
from paradedb.expressions import Proximity, ProximityRegex, ProximityArray
Article.objects.filter(
Proximity(
["python", "##" 1, "##>", "django"],
field="title"
)
)
# using proximity regex and proximity array
Article.objects.filter(
Proximity(
(
"django",
"##",
"1",
"##>",
ProximityRegex("m.*"),
"##",
100,
"##>",
ProximityArray(["wow", ProximityRegex("wow.*", 10)]),
),
field='title'
)
)
JsonOp¶
- ParadeDB Json SubScript Querying
- supported in version - 0.20.5+
JsonOp(field: str, *keys: str, value: str | int | models.Value, op: typing.Literal["@@@", "|||", "===", "###", "&&&"] = "@@@")
Documentation link: -
Field Path Parsing Rule
If a field path contains any of the following operators:
matchphrasematch_conjunctionterm
All keys that appear after the operator will be ignored.
Example
from paradedb.expressions import JsonOp
Article.objects.filter(JsonOp("metadata", "read_count", value=models.Value(1)))
Article.objects.filter(JsonOp("metadata", "tags", "name", value='django'))
# using paradedb custom operator with jsonfield
Article.objects.filter(JsonOp("metadata", "tag", "name", "match", value='django'))
# or use with op parameter
Article.objects.filter(JsonOp("metadata", "tag", "name", value='django', op='|||'))