{
  "schema_version": 2,
  "id": "develop/ai/redisvl/api/filter",
  "title": "Filter",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/api/filter/",
  "summary": "",
  "aliases": [
    "/integrate/redisvl/api/filter"
  ],
  "tags": [],
  "last_updated": "2026-10-12T09:34:21+02:00",
  "page_type": "content",
  "content_hash": "b10f5d7ee16aab89b198bc20f03aebc6fbc2961cdcc8a0fbaf1143ea5fff8cd4",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "<a id=\"filter-api\"></a>"
    },
    {
      "id": "filterexpression",
      "title": "FilterExpression",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-filterexpression_filternone-operatornone-leftnone-rightnone",
      "title": "`class FilterExpression(_filter=None, operator=None, left=None, right=None)`",
      "role": "content",
      "text": "A FilterExpression is a logical combination of filters in RedisVL.\n\nFilterExpressions can be combined using the & and | operators to create\ncomplex expressions that evaluate to the Redis Query language.\n\nThis presents an interface by which users can create complex queries\nwithout having to know the Redis Query language.\n\n[code example]\n\nThis can be combined with the VectorQuery class to create a query:\n\n[code example]\n\n> [!NOTE]\n> Filter expressions are typically not called directly. Instead they are\n> built by combining filter statements using the & and | operators.\n\n* **Parameters:**\n  * **\\_filter** (*str* *|* *None*)\n  * **operator** (*FilterOperator* *|* *None*)\n  * **left** ([FilterExpression](#filterexpression) *|* *None*)\n  * **right** ([FilterExpression](#filterexpression) *|* *None*)"
    },
    {
      "id": "tag",
      "title": "Tag",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-tagfield",
      "title": "`class Tag(field)`",
      "role": "content",
      "text": "A Tag filter can be applied to Tag fields\n\n* **Parameters:**\n  **field** (*str*)\n\n#### `__eq__(other)`\n\nCreate a Tag equality filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *List* *[* *str* *]* *,* *str* *]*) – The tag(s) to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__mod__(other)`\n\nCreate a Tag wildcard filter expression for pattern matching.\n\nThis enables wildcard pattern matching on tag fields using the `*`\ncharacter. Unlike the equality operator, wildcards are not escaped,\nallowing patterns with wildcards in any position, such as prefix\n(`\"tech*\"`), suffix (`\"*tech\"`), or middle (`\"*tech*\"`)\nmatches.\n\n* **Parameters:**\n  **other** (*Union* *[* *List* *[* *str* *]* *,* *str* *]*) – The tag pattern(s) to filter on.\n  Use `*` for wildcard matching (e.g., `\"tech*\"`, `\"*tech\"`,\n  or `\"*tech*\"`).\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__ne__(other)`\n\nCreate a Tag inequality filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *List* *[* *str* *]* *,* *str* *]*) – The tag(s) to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__str__()`\n\nReturn the Redis Query string for the Tag filter\n\n* **Return type:**\n  str"
    },
    {
      "id": "text",
      "title": "Text",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-textfield",
      "title": "`class Text(field)`",
      "role": "content",
      "text": "A Text is a FilterField representing a text field in a Redis index.\n\n> [!NOTE]\n> `==` and `!=` match the value as a quoted phrase. Any `\"` in the\n> value becomes a space first, so the value cannot close that phrase; a\n> quote already separates tokens at index time, so this matches the same\n> documents that escaping it never could. A value of nothing but quotes\n> therefore becomes an empty phrase, which `==` matches no document\n> against. `%` is the pattern operator and interpolates its value\n> untouched.\n\n* **Parameters:**\n  **field** (*str*)\n\n#### `__eq__(other)`\n\nCreate a Text equality filter expression. These expressions yield\nfilters that enforce an exact match on the supplied term(s).\n\n* **Parameters:**\n  **other** (*str*) – The text value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__mod__(other)`\n\nCreate a Text \"LIKE\" filter expression. A flexible expression that\nyields filters that can use a variety of additional operators like\nwildcards (\\*), fuzzy matches (%%), or combinatorics (|) of the supplied\nterm(s).\n\n* **Parameters:**\n  **other** (*str*) – The text value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n> [!NOTE]\n> The value is interpolated raw, which is what makes `*`, `%%` and\n> `|` work. A value carrying a `)` therefore closes this clause and\n> has its remainder parsed as query syntax, past any surrounding\n> filter. Pass only patterns your own code composes; for a value you\n> did not construct, use `==`, which matches it as a literal phrase.\n\n#### `__ne__(other)`\n\nCreate a Text inequality filter expression. These expressions yield\nnegated filters on exact matches on the supplied term(s). Opposite of an\nequality filter expression.\n\n* **Parameters:**\n  **other** (*str*) – The text value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__str__()`\n\nReturn the Redis Query string for the Text filter\n\n* **Return type:**\n  str"
    },
    {
      "id": "num",
      "title": "Num",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-numfield",
      "title": "`class Num(field)`",
      "role": "content",
      "text": "A Num is a FilterField representing a numeric field in a Redis index.\n\n* **Parameters:**\n  **field** (*str*)\n\n#### `__eq__(other)`\n\nCreate a Numeric equality filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__ge__(other)`\n\nCreate a Numeric greater than or equal to filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__gt__(other)`\n\nCreate a Numeric greater than filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__le__(other)`\n\nCreate a Numeric less than or equal to filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__lt__(other)`\n\nCreate a Numeric less than filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__ne__(other)`\n\nCreate a Numeric inequality filter expression.\n\n* **Parameters:**\n  **other** (*Union* *[* *int* *,* *float* *]*) – The value to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__str__()`\n\nReturn the Redis Query string for the Numeric filter\n\n* **Return type:**\n  str\n\n#### `between(start, end, inclusive='both')`\n\nOperator for searching values between two numeric values.\n\n* **Parameters:**\n  * **start** (*Union* *[* *int* *,* *float* *]*) – The lower bound of the range.\n  * **end** (*Union* *[* *int* *,* *float* *]*) – The upper bound of the range.\n  * **inclusive** (*str* *,* *optional*) – Which bounds to include: \"both\",\n    \"neither\", \"left\" or \"right\". Defaults to \"both\".\n* **Raises:**\n  * **TypeError** – If either bound is not an `int`, a `float`, or\n        another `numbers.Real`. numpy scalars qualify; `Decimal`\n        and `str` do not.\n  * **ValueError** – If either bound is NaN, or if `inclusive` is not one\n        of the four accepted values.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]"
    },
    {
      "id": "geo",
      "title": "Geo",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-geofield",
      "title": "`class Geo(field)`",
      "role": "content",
      "text": "A Geo is a FilterField representing a geographic (longitude, latitude)\nfield in a Redis index.\n\n> [!NOTE]\n> Redis indexes latitudes only within +/-85.05112878 degrees (EPSG:900913).\n> A document or a query center nearer a pole than that is silently\n> excluded: the query returns no error and no results, at any radius.\n\n* **Parameters:**\n  **field** (*str*)\n\n#### `__eq__(other)`\n\nCreate a geographic filter within a specified GeoRadius.\n\n* **Parameters:**\n  **other** ([GeoRadius](#georadius)) – The geographic spec to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__ne__(other)`\n\nCreate a geographic filter outside of a specified GeoRadius.\n\n* **Parameters:**\n  **other** ([GeoRadius](#georadius)) – The geographic spec to filter on.\n* **Return type:**\n  [FilterExpression](#filterexpression)\n\n[code example]\n\n#### `__str__()`\n\nReturn the Redis Query string for the Geo filter\n\n* **Return type:**\n  str"
    },
    {
      "id": "georadius",
      "title": "GeoRadius",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-georadiuslongitude-latitude-radius1-unitkm",
      "title": "`class GeoRadius(longitude, latitude, radius=1, unit='km')`",
      "role": "content",
      "text": "A GeoRadius is a GeoSpec representing a geographic radius.\n\nCreate a GeoRadius specification (GeoSpec)\n\n* **Parameters:**\n  * **longitude** (*float*) – The longitude of the center of the radius, in\n    degrees, from -180 to 180.\n  * **latitude** (*float*) – The latitude of the center of the radius, in\n    degrees, from -90 to 90.\n  * **radius** (*float* *,* *optional*) – The radius of the circle, in `unit`,\n    greater than 0. Fractional radii are sent as given, so 0.5 with\n    a unit of \"km\" is half a kilometre. Defaults to 1.\n  * **unit** (*str* *,* *optional*) – The unit of the radius. Defaults to \"km\".\n* **Raises:**\n  * **TypeError** – If a coordinate or the radius is not an `int`, a\n        `float`, or another `numbers.Real`. numpy scalars qualify;\n        `Decimal` and `str` do not.\n  * **ValueError** – If a coordinate is NaN, infinite, or outside its range,\n        if the radius is NaN, infinite, or not greater than 0, or if\n        the unit is not a string spelling one of \"m\", \"km\", \"mi\", or\n        \"ft\".\n\n#### `__init__(longitude, latitude, radius=1, unit='km')`\n\nCreate a GeoRadius specification (GeoSpec)\n\n* **Parameters:**\n  * **longitude** (*float*) – The longitude of the center of the radius, in\n    degrees, from -180 to 180.\n  * **latitude** (*float*) – The latitude of the center of the radius, in\n    degrees, from -90 to 90.\n  * **radius** (*float* *,* *optional*) – The radius of the circle, in `unit`,\n    greater than 0. Fractional radii are sent as given, so 0.5 with\n    a unit of \"km\" is half a kilometre. Defaults to 1.\n  * **unit** (*str* *,* *optional*) – The unit of the radius. Defaults to \"km\".\n* **Raises:**\n  * **TypeError** – If a coordinate or the radius is not an `int`, a\n        `float`, or another `numbers.Real`. numpy scalars qualify;\n        `Decimal` and `str` do not.\n  * **ValueError** – If a coordinate is NaN, infinite, or outside its range,\n        if the radius is NaN, infinite, or not greater than 0, or if\n        the unit is not a string spelling one of \"m\", \"km\", \"mi\", or\n        \"ft\"."
    },
    {
      "id": "timestamp",
      "title": "Timestamp",
      "role": "content",
      "text": ""
    },
    {
      "id": "class-timestampfield",
      "title": "`class Timestamp(field)`",
      "role": "content",
      "text": "A timestamp filter for querying date/time fields in Redis.\n\nThis filter can handle various date and time formats, including:\n- datetime objects (with or without timezone)\n- date objects\n- ISO-8601 formatted strings\n- Unix timestamps (as integers or floats)\n\nAll timestamps are converted to Unix timestamps in UTC for consistency.\nBare date values and date-only ISO strings are anchored to the UTC calendar\nday, not the host’s local day, and naive datetimes are read as UTC.\n\n* **Parameters:**\n  **field** (*str*)\n\n#### `__eq__(other)`\n\nFilter for timestamps equal to the specified value.\nFor date objects (without time), this matches the entire UTC calendar\nday, from 00:00:00 to 23:59:59.999999 UTC.\n\n* **Parameters:**\n  **other** (*datetime* *|* *date* *|* *str* *|* *int* *|* *float*) – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `__ge__(other)`\n\nFilter for timestamps greater than or equal to the specified value.\n\nFor a bare date (or date-only ISO string), this means from the *start* of\nthat UTC day, so the day itself is included.\n\n* **Parameters:**\n  **other** – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `__gt__(other)`\n\nFilter for timestamps greater than the specified value.\n\nFor a bare date (or date-only ISO string), this means after the *end* of\nthat UTC day, so the day itself is excluded.\n\n* **Parameters:**\n  **other** – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `__le__(other)`\n\nFilter for timestamps less than or equal to the specified value.\n\nFor a bare date (or date-only ISO string), this means through the *end* of\nthat UTC day, so the day itself is included.\n\n* **Parameters:**\n  **other** – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `__lt__(other)`\n\nFilter for timestamps less than the specified value.\n\nFor a bare date (or date-only ISO string), this means before the *start*\nof that UTC day, so the day itself is excluded.\n\n* **Parameters:**\n  **other** – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `__ne__(other)`\n\nFilter for timestamps not equal to the specified value.\nFor date objects (without time), this excludes the entire UTC calendar\nday, from 00:00:00 to 23:59:59.999999 UTC.\n\n* **Parameters:**\n  **other** (*datetime* *|* *date* *|* *str* *|* *int* *|* *float*) – A datetime, date, ISO string, or Unix timestamp\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self\n\n#### `between(start, end, inclusive='both')`\n\nFilter for timestamps between start and end (inclusive).\n\nBare dates (and date-only ISO strings) span whole UTC calendar days:\nstart anchors to 00:00:00 of its day and end to 23:59:59.999999 of its\nday, so both endpoint days are covered in full.\n\n* **Parameters:**\n  * **start** – A datetime, date, ISO string, or Unix timestamp\n  * **end** – A datetime, date, ISO string, or Unix timestamp\n  * **inclusive** (*str*) – Which endpoints to include – \"both\" (default), \"left\",\n    \"right\", or \"neither\".\n* **Returns:**\n  The filter object for method chaining\n* **Return type:**\n  self"
    }
  ],
  "examples": [
    {
      "id": "class-filterexpression_filternone-operatornone-leftnone-rightnone-ex0",
      "language": "python",
      "code": "from redisvl.query.filter import Tag, Num\n\nbrand_is_nike = Tag(\"brand\") == \"nike\"\nprice_is_over_100 = Num(\"price\") < 100\nf = brand_is_nike & price_is_over_100\n\nprint(str(f))\n\n>> (@brand:{nike} @price:[-inf (100)])",
      "section_id": "class-filterexpression_filternone-operatornone-leftnone-rightnone"
    },
    {
      "id": "class-filterexpression_filternone-operatornone-leftnone-rightnone-ex1",
      "language": "python",
      "code": "from redisvl.query import VectorQuery\n\nv = VectorQuery(\n    vector=[0.1, 0.1, 0.5, ...],\n    vector_field_name=\"product_embedding\",\n    return_fields=[\"product_id\", \"brand\", \"price\"],\n    filter_expression=f,\n)",
      "section_id": "class-filterexpression_filternone-operatornone-leftnone-rightnone"
    },
    {
      "id": "class-tagfield-ex0",
      "language": "python",
      "code": "from redisvl.query.filter import Tag\n\nf = Tag(\"brand\") == \"nike\"",
      "section_id": "class-tagfield"
    },
    {
      "id": "class-tagfield-ex1",
      "language": "python",
      "code": "from redisvl.query.filter import Tag\n\nf = Tag(\"category\") % \"tech*\"               # Prefix match\nf = Tag(\"category\") % \"*tech\"               # Suffix match\nf = Tag(\"category\") % \"*tech*\"              # Contains match\nf = Tag(\"category\") % \"elec*|*soft\"         # Multiple wildcard patterns\nf = Tag(\"category\") % [\"tech*\", \"*science\"] # List of patterns",
      "section_id": "class-tagfield"
    },
    {
      "id": "class-tagfield-ex2",
      "language": "python",
      "code": "from redisvl.query.filter import Tag\nf = Tag(\"brand\") != \"nike\"",
      "section_id": "class-tagfield"
    },
    {
      "id": "class-textfield-ex0",
      "language": "python",
      "code": "from redisvl.query.filter import Text\n\nf = Text(\"job\") == \"engineer\"",
      "section_id": "class-textfield"
    },
    {
      "id": "class-textfield-ex1",
      "language": "python",
      "code": "from redisvl.query.filter import Text\n\nf = Text(\"job\") % \"engine*\"         # suffix wild card match\nf = Text(\"job\") % \"%%engine%%\"      # fuzzy match w/ Levenshtein Distance\nf = Text(\"job\") % \"engineer|doctor\" # contains either term in field\nf = Text(\"job\") % \"engineer doctor\" # contains both terms in field",
      "section_id": "class-textfield"
    },
    {
      "id": "class-textfield-ex2",
      "language": "python",
      "code": "from redisvl.query.filter import Text\n\nf = Text(\"job\") != \"engineer\"",
      "section_id": "class-textfield"
    },
    {
      "id": "class-numfield-ex0",
      "language": "python",
      "code": "from redisvl.query.filter import Num\nf = Num(\"zipcode\") == 90210",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex1",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"age\") >= 18",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex2",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"age\") > 18",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex3",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"age\") <= 18",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex4",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"age\") < 18",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex5",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"zipcode\") != 90210",
      "section_id": "class-numfield"
    },
    {
      "id": "class-numfield-ex6",
      "language": "python",
      "code": "from redisvl.query.filter import Num\n\nf = Num(\"age\").between(18, 65)\nf = Num(\"age\").between(18, 65, inclusive=\"neither\")",
      "section_id": "class-numfield"
    },
    {
      "id": "class-geofield-ex0",
      "language": "python",
      "code": "from redisvl.query.filter import Geo, GeoRadius\n\nf = Geo(\"location\") == GeoRadius(-122.4194, 37.7749, 1, unit=\"m\")",
      "section_id": "class-geofield"
    },
    {
      "id": "class-geofield-ex1",
      "language": "python",
      "code": "from redisvl.query.filter import Geo, GeoRadius\n\nf = Geo(\"location\") != GeoRadius(-122.4194, 37.7749, 1, unit=\"m\")",
      "section_id": "class-geofield"
    }
  ]
}
