{
  "schema_version": 2,
  "id": "develop/ai/search-and-query/advanced-concepts/dialects",
  "title": "Query dialects",
  "url": "https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/dialects/",
  "summary": "Learn how to use query dialects",
  "aliases": [
    "/develop/interact/search-and-query/advanced-concepts/dialects"
  ],
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-11T15:33:04+01:00",
  "page_type": "content",
  "content_hash": "62596ae38468ab015e67ae3d1e246b3975dd381ecc3773b623de680761dcc074",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis Open Source currently supports four query dialects for use with the [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search), [`FT.AGGREGATE`](https://redis.io/docs/latest/commands/ft.aggregate), and other Redis Search commands.\nDialects provide for enhancing the query API incrementally, introducing innovative behaviors and new features that support new use cases in a way that does not break the API for existing applications.\n\n> [!NOTE]\n> Dialects 1, 3, and 4 are deprecated in Redis 8 in Redis Open Source. However, DIALECT 1 remains the default."
    },
    {
      "id": "dialect-1-deprecated",
      "title": "`DIALECT 1` (Deprecated)",
      "role": "content",
      "text": "Dialect version 1 was the default query syntax dialect from the first release of search and query until dialect version 2 was introduced with version [2.4](https://github.com/RediSearch/RediSearch/releases/tag/v2.4.3).\nThis dialect is also the default dialect. See below for information about changing the default dialect."
    },
    {
      "id": "dialect-2",
      "title": "`DIALECT 2`",
      "role": "content",
      "text": "Dialect version 2 was introduced in the [2.4](https://github.com/RediSearch/RediSearch/releases/tag/v2.4.3) release to address query parser inconsistencies found in previous versions of Redis. Dialect version 1 remains the default dialect. To use dialect version 2, append `DIALECT 2` to your query command.\nSupport for vector search also was introduced in the 2.4 release and requires `DIALECT 2`. See [here](https://redis.io/docs/latest/develop/ai/search-and-query/query/vector-search) for more details.\n`FT.SEARCH ... DIALECT 2`\n\nIt was determined that under certain conditions some query parsing rules did not behave as originally intended.\nParticularly, some queries containing the operators below could return unexpected results.\n\n1. AND, multi-word phrases that imply intersection\n1. `\"...\"` (exact), `~` (optional), `-` (negation), and `%` (fuzzy)\n1. OR, words separated by the `|` (pipe) character that imply union\n1. wildcard characters\n\nExisting queries that used dialect 1 may behave differently using dialect 2 if they fall into any of the following categories:\n\n1. Your query has a field modifier followed by multiple words. Consider the sample query:\n\n    `@name:James Brown`\n\n    Here, the field modifier `@name` is followed by two words, `James` and `Brown`.\n\n    In `DIALECT 1`, this query would be interpreted as find `James Brown` in the `@name` field.\n    In `DIALECT 2`, this query would be interpreted as find `James` in the `@name` field, and `Brown` in any text field. In other words, it would be interpreted as `(@name:James) Brown`. \n    In `DIALECT 2`, you could achieve the dialect 1 behavior by updating your query to `@name:(James Brown)`.\n\n1. Your query uses `\"...\"`, `~`, `-`, and/or `%`. Consider a simple query with negation:\n\n    `-hello world`\n\n    In `DIALECT 1`, this query is interpreted as find values in any field that do not contain `hello` and do not contain `world`; the equivalent of `-(hello world)` or `-hello -world`.\n    In `DIALECT 2`, this query is interpreted as `-hello` and `world` (only `hello` is negated).\n    In `DIALECT 2`, you could achieve the dialect 1 behavior by updating your query to `-(hello world)`.\n\n1. Your query used `|`. Consider the simple query:\n\n    `hello world | \"goodbye\" moon`\n\n    In `DIALECT 1`, this query is interpreted as searching for `(hello world | \"goodbye\") moon`.\n    In `DIALECT 2`, this query is interpreted as searching for either `hello world` `\"goodbye\" moon`.\n\n1. Your query uses a wildcard pattern. Consider the simple query:\n\n    `\"w'foo*bar?'\"`\n\n    As shown above, you must use double quotes to contain the `w` pattern.\n\nWith `DIALECT 2` you can use un-escaped spaces in tag queries, even with stopwords.\n\n> [!NOTE]\n> `DIALECT 2` is required with vector searches.\n\n`DIALECT 2` functionality was enhanced in the 2.10 release.\nIt introduces support for new comparison operators for `NUMERIC` fields:\n\n* `==` (equal).\n  \n  `FT.SEARCH idx \"@numeric==3456\" DIALECT 2`\n\n  and\n\n  `FT.SEARCH idx \"@numeric:[3456]\" DIALECT 2`\n* `!=` (not equal).\n  \n  `FT.SEARCH idx \"@numeric!=3456\" DIALECT 2`\n* `>` (greater than).\n  \n  `FT.SEARCH idx \"@numeric>3456\" DIALECT 2`\n* `>=` (greater than or equal).\n  \n  `FT.SEARCH idx \"@numeric>=3456\" DIALECT 2`\n* `<` (less than).\n  \n  `FT.SEARCH idx \"@numeric<3456\" DIALECT 2`\n* `<=` (less than or equal).\n  \n  `FT.SEARCH idx \"@numeric<=3456\" DIALECT 2`\n\nThe Dialect version 2 enhancements also introduce simplified syntax for logical operations:\n\n* `|` (or).\n\n  `FT.SEARCH idx \"@tag:{3d3586fe-0416-4572-8ce1 | 3d3586fe-0416-6758-4ri8}\" DIALECT 2`\n\n  which is equivalent to\n\n  `FT.SEARCH idx \"(@tag:{3d3586fe-0416-4572-8ce1} | @tag{3d3586fe-0416-6758-4ri8})\" DIALECT 2`\n\n* `<space>` (and).\n\n  `FT.SEARCH idx \"(@tag:{3d3586fe-0416-4572-8ce1} @tag{3d3586fe-0416-6758-4ri8})\" DIALECT 2`\n\n* `-` (negation).\n\n  `FT.SEARCH idx \"(@tag:{3d3586fe-0416-4572-8ce1} -@tag{3d3586fe-0416-6758-4ri8})\" DIALECT 2`\n\n* `~` (optional/proximity).\n\n  `FT.SEARCH idx \"(@tag:{3d3586fe-0416-4572-8ce1} ~@tag{3d3586fe-0416-6758-4ri8})\" DIALECT 2`"
    },
    {
      "id": "dialect-3-deprecated",
      "title": "`DIALECT 3` (Deprecated)",
      "role": "content",
      "text": "Dialect version 3 was introduced in the [2.6](https://github.com/RediSearch/RediSearch/releases/tag/v2.6.3) release. This version introduced support for multi-value indexing and querying of attributes for any attribute type ( [TEXT](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-text), [TAG](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-tag), [NUMERIC](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-numeric), [GEO](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-geo) and [VECTOR](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-vector)) defined by a [JSONPath](https://redis.io/docs/latest/develop/data-types/json/path) leading to an array or multiple scalar values. Support for [GEOSHAPE](https://redis.io/docs/latest/develop/ai/search-and-query/query/geo-spatial) queries was also introduced in this version.\n\nThe primary difference between dialects version 2 and version 3 is that JSON is returned rather than scalars for multi-value attributes. Apart from specifying `DIALECT 3` at the end of a [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search) command, there are no other syntactic changes. Dialect version 1 remains the default dialect. To use dialect version 3, append `DIALECT 3` to your query command.\n\n`FT.SEARCH ... DIALECT 3`\n\n**Example**\n\nSample JSON:\n\n[code example]\n\nCreate an index:\n\n[code example]\n\nNow search, with and without `DIALECT 3`.\n\n- With dialect 1 (default):\n\n    [code example]\n    \n    Only the first element of the expected two elements is returned.\n\n- With dialect 3:\n\n    [code example]\n\n    Both elements are returned."
    },
    {
      "id": "dialect-4-deprecated",
      "title": "`DIALECT 4` (Deprecated)",
      "role": "content",
      "text": "Dialect version 4 was introduced in the [2.8](https://github.com/RediSearch/RediSearch/releases/tag/v2.8.4) release. It introduces performance optimizations for sorting operations on [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search) and [`FT.AGGREGATE`](https://redis.io/docs/latest/commands/ft.aggregate). Apart from specifying `DIALECT 4` at the end of a [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search) command, there are no other syntactic changes. Dialect version 1 remains the default dialect. To use dialect version 4, append `DIALECT 4` to your query command.\n\n`FT.SEARCH ... DIALECT 4`\n\nDialect version 4 will improve performance in four different scenarios:\n\n1. **Skip sorter** - applied when there is no sorting to be done. The query can return once it reaches the `LIMIT` of requested results.\n1. **Partial range** - applied when there is a `SORTBY` on a numeric field, either with no filter or with a filter by the same numeric field. Such queries will iterate on a range large enough to satisfy the `LIMIT` of requested results.\n1. **Hybrid** - applied when there is a `SORTBY` on a numeric field in addition to another non-numeric filter. It could be the case that some results will get filtered, leaving too small a range to satisfy any specified `LIMIT`. In such cases, the iterator then is re-wound and additional iterations occur to collect result up to the requested `LIMIT`.\n1. **No optimization** - If there is a sort by score or by a non-numeric field, there is no other option but to retrieve all results and compare their values to the search parameters.\n\nYou can also use `WITHOUTCOUNT` in place of `DIALECT 4` when used with either FT.SEARCH or FT.AGGREGATE."
    },
    {
      "id": "use-ftexplaincli-to-compare-dialects",
      "title": "Use `FT.EXPLAINCLI` to compare dialects",
      "role": "content",
      "text": "The [`FT.EXPLAINCLI`](https://redis.io/docs/latest/commands/ft.explaincli) command is a powerful tool that provides a window into the inner workings of your queries. It's like a roadmap that details your query's journey from start to finish.\n\nWhen you run [`FT.EXPLAINCLI`](https://redis.io/docs/latest/commands/ft.explaincli), it returns an array representing the execution plan of a complex query. This plan is a step-by-step guide of how Redis interprets your query and how it plans to fetch results. It's a behind-the-scenes look at the process, giving you insights into how the search engine works.\n\nThe [`FT.EXPLAINCLI`](https://redis.io/docs/latest/commands/ft.explaincli) accepts a `DIALECT` argument, allowing you to execute the query using different dialect versions, allowing you to compare the resulting query plans.\n\nTo use [`FT.EXPLAINCLI`](https://redis.io/docs/latest/commands/ft.explaincli), you need to provide an index and a query predicate. The index is the name of the index you created using [`FT.CREATE`](https://redis.io/docs/latest/commands/ft.create), and the query predicate is the same as if you were sending it to [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search) or [`FT.AGGREGATE`](https://redis.io/docs/latest/commands/ft.aggregate).\n\nHere's an example of how to use [`FT.EXPLAINCLI`](https://redis.io/docs/latest/commands/ft.explaincli) to understand differences in dialect versions 1 and 2.\n\nNegation of the intersection between tokens `hello` and `world`:\n\n[code example]\n\nIntersection of the negation of the token `hello` together with token `world`:\n\n[code example]\n\nSame result as `DIALECT 1`:\n\n[code example]\n\n> [!NOTE]\n> [`FT.EXPLAIN`](https://redis.io/docs/latest/commands/ft.explain) doesn't execute the query. It only explains the plan. It's a way to understand how your query is interpreted by Redis Search, which can be invaluable when you're trying to optimize your searches."
    },
    {
      "id": "change-the-default-dialect",
      "title": "Change the default dialect",
      "role": "content",
      "text": "The default dialect is `DIALECT 1`. If you wish to change that, you can do so by using the `DEFAULT_DIALECT` parameter when loading the RediSearch module:\n\n[code example]\n\nYou can also change the query dialect on an already running server using the `FT.CONFIG` command:\n\n[code example]"
    }
  ],
  "examples": [
    {
      "id": "dialect-3-deprecated-ex0",
      "language": "plaintext",
      "code": "{\n  \"id\": 123,\n  \"underlyings\": [\n    {\n      \"currency\": \"USD\",\n      \"spot\": 99,\n      \"underlier\": \"AAPL UW\"\n    },\n    {\n      \"currency\": \"USD\",\n      \"spot\": 100,\n      \"underlier\": \"NFLX UW\"\n    }\n  ]\n}",
      "section_id": "dialect-3-deprecated"
    },
    {
      "id": "dialect-3-deprecated-ex1",
      "language": "plaintext",
      "code": "FT.CREATE js_idx ON JSON PREFIX 1 js: SCHEMA $.underlyings[*].underlier AS und TAG",
      "section_id": "dialect-3-deprecated"
    },
    {
      "id": "dialect-3-deprecated-ex2",
      "language": "plaintext",
      "code": "ft.search js_idx * return 1 und\n      1) (integer) 1\n      2) \"js:1\"\n      3) 1) \"und\"\n         2) \"AAPL UW\"",
      "section_id": "dialect-3-deprecated"
    },
    {
      "id": "dialect-3-deprecated-ex3",
      "language": "plaintext",
      "code": "ft.search js_idx * return 1 und DIALECT 3\n        1) (integer) 1\n        2) \"js:1\"\n        3) 1) \"und\"\n           2) \"[\\\"AAPL UW\\\",\\\"NFLX UW\\\"]\"",
      "section_id": "dialect-3-deprecated"
    },
    {
      "id": "use-ftexplaincli-to-compare-dialects-ex0",
      "language": "FT.EXPLAINCLI idx:dialects \"-hello world\" DIALECT 1",
      "code": "1) NOT {\n2)   INTERSECT {\n3)     hello\n4)     world\n5)   }\n6) }\n7)",
      "section_id": "use-ftexplaincli-to-compare-dialects"
    },
    {
      "id": "use-ftexplaincli-to-compare-dialects-ex1",
      "language": "plaintext",
      "code": "FT.EXPLAINCLI idx:dialects \"-hello world\" DIALECT 2\n 1) INTERSECT {\n 2)   NOT {\n 3)     hello\n 4)   }\n 5)   UNION {\n 6)     world\n 7)     +world(expanded)\n 8)   }\n 9) }\n10)",
      "section_id": "use-ftexplaincli-to-compare-dialects"
    },
    {
      "id": "use-ftexplaincli-to-compare-dialects-ex2",
      "language": "plaintext",
      "code": "FT.EXPLAINCLI idx:dialects \"-(hello world)\" DIALECT 2\n1) NOT {\n2)   INTERSECT {\n3)     hello\n4)     world\n5)   }\n6) }\n7)",
      "section_id": "use-ftexplaincli-to-compare-dialects"
    },
    {
      "id": "change-the-default-dialect-ex0",
      "language": "plaintext",
      "code": "$ redis-server --loadmodule ./redisearch.so DEFAULT_DIALECT 2",
      "section_id": "change-the-default-dialect"
    },
    {
      "id": "change-the-default-dialect-ex1",
      "language": "plaintext",
      "code": "FT.CONFIG SET DEFAULT_DIALECT 2",
      "section_id": "change-the-default-dialect"
    }
  ]
}
