{
  "schema_version": 2,
  "id": "develop/get-started/search-tutorial/indexing",
  "title": "Create an index",
  "url": "https://redis.io/docs/latest/develop/get-started/search-tutorial/indexing/",
  "summary": "Create a search index over your JSON documents with FT.CREATE, choose the right field types, and understand how Redis indexes arrays.",
  "aliases": [
    "/get-started/search-tutorial/indexing/"
  ],
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-11T15:36:02+01:00",
  "page_type": "content",
  "content_hash": "8ffad55a7401d52ee31908c9a73a91c57c5809abe6ec60b792656433be4b1b61",
  "sections": [
    {
      "id": "what-an-index-does",
      "title": "What an index does",
      "role": "content",
      "text": "When you create an index, you give Redis three things:\n\n1. **What to index** &mdash; which keys belong to the index, selected by a key prefix (here, `product:`).\n2. **The data type** &mdash; whether those keys hold hashes (`ON HASH`) or JSON documents (`ON JSON`).\n3. **The schema** &mdash; which fields to index, the path to each one, and what type each field is.\n\nOnce the index exists, Redis keeps it up to date automatically. Any `product:` document you add or change after creating the index is indexed immediately, and the documents you loaded earlier are indexed right away."
    },
    {
      "id": "field-types",
      "title": "Field types",
      "role": "content",
      "text": "Redis Search has a few core field types. Choosing the right one for each field determines how you can query it:\n\n| Field type | Use it for | Example query |\n| --- | --- | --- |\n| `TEXT` | Human language you want to search by words and partial matches. | find products whose description contains *wireless* |\n| `TAG` | Exact-value labels and categories you filter on as a whole. | find products where category is exactly *Audio* |\n| `NUMERIC` | Numbers you filter by range or sort by. | find products priced between 0 and 100 |\n| `VECTOR` | Embeddings for similarity search (covered in the [last step](https://redis.io/docs/latest/develop/get-started/search-tutorial/vector-search)). | find products similar in meaning to a query |\n\nFor the catalog, a good mapping is: `name` and `description` are `TEXT` (you want word search), `brand` and `category` are `TAG` (exact labels), and `price`, `rating`, `review_count`, `stock`, and `release_year` are `NUMERIC`. The `features` field is a list of exact labels, so it is also a `TAG`."
    },
    {
      "id": "create-the-index",
      "title": "Create the index",
      "role": "content",
      "text": "<details><summary>Reload products data</summary>\nFoundational: Load the tutorial dataset as JSON documents under a shared key prefix using JSON.SET\n\n**Difficulty:** Beginner\n\n**Commands:** JSON.SET\n\n**Complexity:**\n- JSON.SET: O(M+N)\n\n**Available in:** Redis CLI, Python\n\n##### Redis CLI\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\n</details>\n\nUse [FT.CREATE](https://redis.io/docs/latest/commands/ft.create) to define the index. Because the data is JSON, each field is identified by a [JSONPath](https://redis.io/docs/latest/develop/data-types/json/path) expression, and `AS` gives it a short alias to use in queries:\n\nFoundational: Create an index over JSON documents with FT.CREATE, mapping JSONPaths to TEXT, TAG, and NUMERIC fields\n\n**Difficulty:** Beginner\n\n**Commands:** FT.CREATE\n\n**Complexity:**\n- FT.CREATE: O(K)\n\n**Available in:** Redis CLI, Python\n\n##### Redis CLI\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nA few things to notice:\n\n- **`PREFIX 1 product:`** means \"index every key that starts with `product:`\". The `1` is the number of prefixes that follow.\n- **`AS name`, `AS price`, ...** define the alias you use in queries (`@name`, `@price`). Without an alias, you would have to write the full JSONPath in every query.\n- **`SORTABLE`** on a field lets you sort results by it efficiently. Add it to fields you expect to sort by, such as `price` and `rating`.\n- **`$.features[*]`** ends in `[*]`, which matters for arrays. More on that next.\n\nYou only create an index once. If you make a mistake, remove it with [FT.DROPINDEX](https://redis.io/docs/latest/commands/ft.dropindex) (this deletes the index, not your documents) and create it again."
    },
    {
      "id": "indexing-arrays-the--you-should-not-forget",
      "title": "Indexing arrays: the `[*]` you should not forget",
      "role": "content",
      "text": "The `features` field is a JSON array like `[\"wireless\", \"bluetooth\", \"waterproof\"]`. To index each element as its own tag, the JSONPath ends in `[*]`:\n\n[code example]\n\nThis is the single most common point of confusion when indexing JSON, so it is worth understanding:\n\n- **With `$.features[*]`**, Redis indexes `wireless`, `bluetooth`, and `waterproof` as three separate tags. A query for `@features:{waterproof}` matches the document.\n- **With `$.features`** (no `[*]`) on a JSON array, the behavior is not what you want for filtering element-by-element.\n\n> [!NOTE]\n> This behavior differs between hashes and JSON, which trips up many newcomers. In a **hash**, a `TAG` field splits on commas by default, so `\"wireless,bluetooth\"` becomes two tags automatically. In **JSON**, there is no automatic splitting: index array elements with `[*]`, or if you store a comma-separated string, add `SEPARATOR \",\"` to the field definition. For the full explanation, see [Index JSON arrays as TAG](https://redis.io/docs/latest/develop/ai/search-and-query/indexing#index-json-arrays-as-tag)."
    },
    {
      "id": "check-the-index",
      "title": "Check the index",
      "role": "content",
      "text": "After creating the index, you can confirm it picked up your documents. [FT.INFO](https://redis.io/docs/latest/commands/ft.info) reports details about an index, including how many documents it contains:\n\nFoundational: Inspect an index with FT.INFO to confirm it exists and see how many documents it contains\n\n**Difficulty:** Beginner\n\n**Commands:** FT.INFO\n\n**Complexity:**\n- FT.INFO: O(1)\n\n**Available in:** Redis CLI, Python\n\n##### Redis CLI\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nLook for `num_docs` in the output; it should be `12`, one for each product you loaded.\n\n> [!NOTE] Try it in Redis Insight\n> In the [Redis Insight Search workspace](https://redis.io/docs/latest/develop/tools/insight/search-workspace), your new `idx:catalog` index appears in the list of indexes. Selecting it shows the schema you just defined &mdash; the fields, their types, and their aliases &mdash; without having to read the raw `FT.INFO` output."
    },
    {
      "id": "next-steps",
      "title": "Next steps",
      "role": "content",
      "text": "Your data is indexed. Continue to [searching and filtering](https://redis.io/docs/latest/develop/get-started/search-tutorial/search) to start asking questions of it."
    }
  ],
  "examples": [
    {
      "id": "create-the-index-ex0",
      "language": "plaintext",
      "code": "> JSON.SET product:1 $ '{\"name\":\"Aurora AcousticPro Headphones\",\"brand\":\"Aurora\",\"category\":\"Audio\",\"price\":199.99,\"rating\":4.6,\"features\":[\"wireless\",\"noise-cancelling\",\"bluetooth\"],\"specs\":{\"color\":\"midnight black\",\"weight_grams\":268}}'\n> JSON.SET product:2 $ '{\"name\":\"Aurora BudsMini Earbuds\",\"brand\":\"Aurora\",\"category\":\"Audio\",\"description\":\"Tiny true-wireless earbuds with a secure in-ear fit and sweat resistance for workouts. The compact charging case slips into a pocket and delivers three full recharges on the go.\",\"price\":89.99,\"rating\":4.3,\"review_count\":942,\"stock\":130,\"release_year\":2023,\"features\":[\"wireless\",\"bluetooth\",\"in-ear\",\"water-resistant\"],\"specs\":{\"color\":\"pearl white\",\"weight_grams\":5,\"warranty_years\":1}}'\n... output truncated for AI-facing Markdown ...\n> JSON.SET product:12 $ '{\"name\":\"Vista Action Cam 4K\",\"brand\":\"Vista\",\"category\":\"Cameras\",\"description\":\"A pocket-sized action camera that shoots stabilized 4K video and is waterproof without a case. Mount it on a helmet or bike and capture your adventures in sharp detail.\",\"price\":299.0,\"rating\":4.3,\"review_count\":455,\"stock\":33,\"release_year\":2023,\"features\":[\"camera\",\"4k\",\"waterproof\",\"wifi\"],\"specs\":{\"color\":\"black\",\"weight_grams\":128,\"warranty_years\":1}}'",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex1",
      "language": "python",
      "code": "catalog = [\n    {\n        \"name\": \"Aurora AcousticPro Headphones\",\n        \"brand\": \"Aurora\",\n        \"category\": \"Audio\",\n        \"description\": (\n            \"Over-ear wireless headphones with active noise cancelling and a \"\n            \"40-hour battery. Plush memory-foam earcups and a lightweight frame \"\n            \"make them comfortable for all-day listening, whether you are \"\n            \"commuting, working, or relaxing at home.\"\n        ),\n        \"price\": 199.99,\n        \"rating\": 4.6,\n        \"review_count\": 1284,\n        \"stock\": 42,\n        \"release_year\": 2024,\n        \"features\": [\"wireless\", \"noise-cancelling\", \"bluetooth\", \"over-ear\"],\n        \"specs\": {\"color\": \"midnight black\", \"weight_grams\": 268, \"warranty_years\": 2},\n    },\n    {\n        \"name\": \"Aurora BudsMini Earbuds\",\n        \"brand\": \"Aurora\",\n        \"category\": \"Audio\",\n        \"description\": (\n            \"Tiny true-wireless earbuds with a secure in-ear fit and sweat \"\n            \"resistance for workouts. The compact charging case slips into a \"\n            \"pocket and delivers three full recharges on the go.\"\n        ),\n        \"price\": 89.99,\n        \"rating\": 4.3,\n        \"review_count\": 942,\n        \"stock\": 130,\n        \"release_year\": 2023,\n        \"features\": [\"wireless\", \"bluetooth\", \"in-ear\", \"water-resistant\"],\n        \"specs\": {\"color\": \"pearl white\", \"weight_grams\": 5, \"warranty_years\": 1},\n    },\n    {\n        \"name\": \"Sonus Boom Portable Speaker\",\n        \"brand\": \"Sonus\",\n        \"category\": \"Audio\",\n        \"description\": (\n            \"A rugged portable Bluetooth speaker with deep bass and a waterproof \"\n            \"shell. Toss it in a bag for the beach or a campsite and enjoy \"\n            \"room-filling sound for up to 20 hours per charge.\"\n        ),\n        \"price\": 129.5,\n        \"rating\": 4.5,\n        \"review_count\": 512,\n        \"stock\": 64,\n        \"release_year\": 2024,\n        \"features\": [\"wireless\", \"bluetooth\", \"portable\", \"waterproof\"],\n        \"specs\": {\"color\": \"slate gray\", \"weight_grams\": 540, \"warranty_years\": 1},\n    },\n    {\n        \"name\": \"Pixma Vortex 15 Laptop\",\n        \"brand\": \"Pixma\",\n        \"category\": \"Computers\",\n        \"description\": (\n            \"A thin-and-light 15-inch laptop with a fast multi-core processor, \"\n            \"16 GB of memory, and a speedy solid-state drive. The backlit keyboard \"\n            \"and bright display make it a capable companion for work and study.\"\n        ),\n        \"price\": 1399.0,\n        \"rating\": 4.7,\n        \"review_count\": 318,\n        \"stock\": 18,\n        \"release_year\": 2024,\n        \"features\": [\"laptop\", \"ssd\", \"backlit-keyboard\", \"lightweight\"],\n        \"specs\": {\"color\": \"space silver\", \"weight_grams\": 1600, \"warranty_years\": 2},\n    },\n    {\n        \"name\": \"Pixma UltraView 27 Monitor\",\n        \"brand\": \"Pixma\",\n        \"category\": \"Computers\",\n        \"description\": (\n            \"A 27-inch 4K monitor with an IPS panel for accurate colors and wide \"\n            \"viewing angles. A single USB-C cable carries video and power, keeping \"\n            \"your desk tidy.\"\n        ),\n        \"price\": 329.99,\n        \"rating\": 4.4,\n        \"review_count\": 221,\n        \"stock\": 27,\n        \"release_year\": 2023,\n        \"features\": [\"monitor\", \"4k\", \"ips\", \"usb-c\"],\n        \"specs\": {\"color\": \"black\", \"weight_grams\": 5200, \"warranty_years\": 3},\n    },\n    {\n        \"name\": \"Clackr Mechanical Keyboard\",\n        \"brand\": \"Clackr\",\n        \"category\": \"Accessories\",\n        \"description\": (\n            \"A compact mechanical keyboard with tactile switches, per-key RGB \"\n            \"lighting, and wireless connectivity. Hot-swappable switches let you \"\n            \"tune the typing feel without soldering.\"\n        ),\n        \"price\": 119.0,\n        \"rating\": 4.8,\n        \"review_count\": 1502,\n        \"stock\": 88,\n        \"release_year\": 2024,\n        \"features\": [\"keyboard\", \"mechanical\", \"rgb\", \"wireless\"],\n        \"specs\": {\"color\": \"graphite\", \"weight_grams\": 720, \"warranty_years\": 2},\n    },\n    {\n        \"name\": \"Glide Pro Wireless Mouse\",\n        \"brand\": \"Glide\",\n        \"category\": \"Accessories\",\n        \"description\": (\n            \"An ergonomic wireless mouse with a high-precision sensor and a \"\n            \"contoured shape that reduces wrist strain. A single charge lasts for \"\n            \"weeks of everyday use.\"\n        ),\n        \"price\": 59.99,\n        \"rating\": 4.2,\n        \"review_count\": 869,\n        \"stock\": 150,\n        \"release_year\": 2022,\n        \"features\": [\"mouse\", \"wireless\", \"ergonomic\"],\n        \"specs\": {\"color\": \"charcoal\", \"weight_grams\": 98, \"warranty_years\": 1},\n    },\n    {\n        \"name\": \"Pulse Series 6 Smartwatch\",\n        \"brand\": \"Pulse\",\n        \"category\": \"Wearables\",\n        \"description\": (\n            \"A sleek smartwatch with built-in GPS, continuous heart-rate \"\n            \"monitoring, and water resistance for swimming. Track workouts, sleep, \"\n            \"and notifications from your wrist.\"\n        ),\n        \"price\": 249.0,\n        \"rating\": 4.5,\n        \"review_count\": 1733,\n        \"stock\": 51,\n        \"release_year\": 2024,\n        \"features\": [\"smartwatch\", \"gps\", \"heart-rate\", \"water-resistant\"],\n        \"specs\": {\"color\": \"rose gold\", \"weight_grams\": 38, \"warranty_years\": 1},\n    },\n    {\n        \"name\": \"Pulse Band Fitness Tracker\",\n        \"brand\": \"Pulse\",\n        \"category\": \"Wearables\",\n        \"description\": (\n            \"A lightweight fitness band that tracks steps, heart rate, and sleep \"\n            \"stages. The slim screen shows daily progress and the battery lasts a \"\n            \"full week between charges.\"\n        ),\n        \"price\": 79.99,\n        \"rating\": 4.1,\n        \"review_count\": 2210,\n        \"stock\": 200,\n        \"release_year\": 2023,\n        \"features\": [\"fitness-tracker\", \"heart-rate\", \"sleep-tracking\"],\n        \"specs\": {\"color\": \"ocean blue\", \"weight_grams\": 24, \"warranty_years\": 1},\n    },\n    {\n        \"name\": \"Lumi Glow Smart Bulb\",\n        \"brand\": \"Lumi\",\n        \"category\": \"Home\",\n        \"description\": (\n            \"A color-changing smart bulb that connects over Wi-Fi and works with \"\n            \"voice assistants. Dim it for movie night or set a warm white for \"\n            \"reading, all from your phone.\"\n        ),\n        \"price\": 24.99,\n        \"rating\": 4.0,\n        \"review_count\": 640,\n        \"stock\": 320,\n        \"release_year\": 2022,\n        \"features\": [\"smart-home\", \"wifi\", \"dimmable\", \"color\"],\n        \"specs\": {\"color\": \"white\", \"weight_grams\": 70, \"warranty_years\": 2},\n    },\n    {\n        \"name\": \"Lumi Climate Smart Thermostat\",\n        \"brand\": \"Lumi\",\n        \"category\": \"Home\",\n        \"description\": (\n            \"A learning smart thermostat that adjusts heating and cooling to your \"\n            \"routine and helps lower energy bills. The crisp display and Wi-Fi app \"\n            \"make scheduling effortless.\"\n        ),\n        \"price\": 149.0,\n        \"rating\": 4.6,\n        \"review_count\": 388,\n        \"stock\": 75,\n        \"release_year\": 2024,\n        \"features\": [\"smart-home\", \"wifi\", \"energy-saving\"],\n        \"specs\": {\"color\": \"white\", \"weight_grams\": 210, \"warranty_years\": 3},\n    },\n    {\n        \"name\": \"Vista Action Cam 4K\",\n        \"brand\": \"Vista\",\n        \"category\": \"Cameras\",\n        \"description\": (\n            \"A pocket-sized action camera that shoots stabilized 4K video and is \"\n            \"waterproof without a case. Mount it on a helmet or bike and capture \"\n            \"your adventures in sharp detail.\"\n        ),\n        \"price\": 299.0,\n        \"rating\": 4.3,\n        \"review_count\": 455,\n        \"stock\": 33,\n        \"release_year\": 2023,\n        \"features\": [\"camera\", \"4k\", \"waterproof\", \"wifi\"],\n        \"specs\": {\"color\": \"black\", \"weight_grams\": 128, \"warranty_years\": 1},\n    },\n]\n\nfor product_id, product in enumerate(catalog, start=1):\n    r.json().set(f\"product:{product_id}\", Path.root_path(), product)",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex2",
      "language": "plaintext",
      "code": "> FT.CREATE idx:catalog ON JSON PREFIX 1 product: SCHEMA $.name AS name TEXT $.brand AS brand TAG SORTABLE $.category AS category TAG $.description AS description TEXT $.price AS price NUMERIC SORTABLE $.rating AS rating NUMERIC SORTABLE $.review_count AS review_count NUMERIC $.stock AS stock NUMERIC $.release_year AS release_year NUMERIC SORTABLE $.features[*] AS features TAG",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex3",
      "language": "python",
      "code": "schema = (\n    TextField(\"$.name\", as_name=\"name\"),\n    TagField(\"$.brand\", as_name=\"brand\", sortable=True),\n    TagField(\"$.category\", as_name=\"category\"),\n    TextField(\"$.description\", as_name=\"description\"),\n    NumericField(\"$.price\", as_name=\"price\", sortable=True),\n    NumericField(\"$.rating\", as_name=\"rating\", sortable=True),\n    NumericField(\"$.review_count\", as_name=\"review_count\"),\n    NumericField(\"$.stock\", as_name=\"stock\"),\n    NumericField(\"$.release_year\", as_name=\"release_year\", sortable=True),\n    TagField(\"$.features[*]\", as_name=\"features\"),\n)\nindex = r.ft(\"idx:catalog\")\nindex.create_index(\n    schema,\n    definition=IndexDefinition(prefix=[\"product:\"], index_type=IndexType.JSON),\n)",
      "section_id": "create-the-index"
    },
    {
      "id": "indexing-arrays-the--you-should-not-forget-ex0",
      "language": "plaintext",
      "code": "$.features[*] AS features TAG",
      "section_id": "indexing-arrays-the--you-should-not-forget"
    },
    {
      "id": "check-the-index-ex0",
      "language": "plaintext",
      "code": "> FT.INFO idx:catalog",
      "section_id": "check-the-index"
    },
    {
      "id": "check-the-index-ex1",
      "language": "python",
      "code": "info = r.ft(\"idx:catalog\").info()\nprint(\"Documents indexed:\", info[\"num_docs\"])  # >>> Documents indexed: 12",
      "section_id": "check-the-index"
    }
  ]
}
