{
  "schema_version": 2,
  "id": "develop/ai/redisvl/concepts/field-attributes",
  "title": "Field Attributes",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/concepts/field-attributes/",
  "summary": "",
  "aliases": [
    "/integrate/redisvl/concepts/field-attributes"
  ],
  "tags": [],
  "last_updated": "2026-06-08T15:46:44+02:00",
  "page_type": "content",
  "content_hash": "807fdb66702f0ca8f62121ba0b00018e99cdc73b99c3473bcd4342d4c24b59d3",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Field attributes customize how Redis indexes and searches your data. Each field type has specific attributes that control indexing behavior, search capabilities, and storage options."
    },
    {
      "id": "common-attributes",
      "title": "Common Attributes",
      "role": "content",
      "text": "These attributes are available on most non-vector field types (text, tag, numeric, geo)."
    },
    {
      "id": "sortable",
      "title": "sortable",
      "role": "content",
      "text": "Enables sorting results by this field. Without `sortable`, you cannot use the field in `ORDER BY` clauses.\n\n**Trade-off**: Sortable fields consume additional memory to maintain a sorted index.\n\n[code example]\n\n[code example]\n\n**Use when**: You need to sort search results by this field (e.g., \"newest first\", \"highest price\")."
    },
    {
      "id": "no_index",
      "title": "no_index",
      "role": "content",
      "text": "Stores the field without indexing it. The field value is available in search results but cannot be used in queries or filters.\n\n**Important**: `no_index` only makes sense when combined with `sortable: true`. A field that is neither indexed nor sortable serves no purpose in the schema.\n\n[code example]\n\n**Use when**: You want to sort by a field but never filter on it, saving index space."
    },
    {
      "id": "index_missing",
      "title": "index_missing",
      "role": "content",
      "text": "Allows searching for documents that don’t have this field. When enabled, you can use `ISMISSING` queries to find documents where the field is absent or null.\n\n[code example]\n\n[code example]\n\n**Use when**: Your data has optional fields and you need to query for documents missing those fields.\n\n**Query example**:\n\n[code example]"
    },
    {
      "id": "text-field-attributes",
      "title": "Text Field Attributes",
      "role": "content",
      "text": "Text fields support full-text search with these additional attributes."
    },
    {
      "id": "weight",
      "title": "weight",
      "role": "content",
      "text": "Controls the importance of this field in relevance scoring. Higher weights make matches in this field rank higher.\n\n[code example]\n\n**Use when**: Some text fields are more important than others for search relevance."
    },
    {
      "id": "no_stem",
      "title": "no_stem",
      "role": "content",
      "text": "Disables stemming for this field. By default, Redis applies stemming so \"running\" matches \"run\". Disable when exact word forms matter.\n\n[code example]\n\n**Use when**: Field contains codes, identifiers, or technical terms where stemming would cause incorrect matches."
    },
    {
      "id": "withsuffixtrie",
      "title": "withsuffixtrie",
      "role": "content",
      "text": "Maintains a suffix trie for optimized suffix and contains queries. Enables efficient `*suffix` and `*contains*` searches.\n\n[code example]\n\n**Use when**: You need to search for patterns like `*@gmail.com` or `*smith*`.\n\n**Trade-off**: Increases memory usage and index build time."
    },
    {
      "id": "phonetic_matcher",
      "title": "phonetic_matcher",
      "role": "content",
      "text": "Enables phonetic matching using the specified algorithm. Matches words that sound similar.\n\n[code example]\n\n**Supported values**: `dm:en` (Double Metaphone English), `dm:fr` (French), `dm:pt` (Portuguese), `dm:es` (Spanish)\n\n**Use when**: Searching names or words where spelling variations should match (e.g., \"Smith\" matches \"Smyth\")."
    },
    {
      "id": "index_empty",
      "title": "index_empty",
      "role": "content",
      "text": "Allows indexing and searching for empty strings. By default, empty strings are not indexed.\n\n[code example]\n\n**Use when**: Empty string is a meaningful value you need to query for."
    },
    {
      "id": "unf-un-normalized-form",
      "title": "unf (Un-Normalized Form)",
      "role": "content",
      "text": "Preserves the original value for sortable fields without normalization. By default, sortable text fields are lowercased for consistent sorting.\n\n**Requires**: `sortable: true`\n\n[code example]\n\n**Use when**: You need case-sensitive sorting or must preserve exact original values."
    },
    {
      "id": "tag-field-attributes",
      "title": "Tag Field Attributes",
      "role": "content",
      "text": "Tag fields are for exact-match filtering on categorical data."
    },
    {
      "id": "separator",
      "title": "separator",
      "role": "content",
      "text": "Specifies the character that separates multiple tags in a single field value. Default is comma (`,`).\n\n[code example]\n\n**Use when**: Your tag values contain commas, or you’re using a different delimiter in your data."
    },
    {
      "id": "case_sensitive",
      "title": "case_sensitive",
      "role": "content",
      "text": "Makes tag matching case-sensitive. By default, tags are lowercased for matching.\n\n[code example]\n\n**Use when**: Tag values are case-sensitive identifiers (SKUs, codes, etc.)."
    },
    {
      "id": "withsuffixtrie-1",
      "title": "withsuffixtrie",
      "role": "content",
      "text": "Same as text fields—enables efficient suffix and contains queries on tags.\n\n[code example]"
    },
    {
      "id": "index_empty-1",
      "title": "index_empty",
      "role": "content",
      "text": "Allows indexing empty tag values.\n\n[code example]"
    },
    {
      "id": "numeric-field-attributes",
      "title": "Numeric Field Attributes",
      "role": "content",
      "text": "Numeric fields support range queries and sorting."
    },
    {
      "id": "unf-un-normalized-form-1",
      "title": "unf (Un-Normalized Form)",
      "role": "content",
      "text": "For sortable numeric fields, preserves the exact numeric representation without normalization.\n\n**Requires**: `sortable: true`\n\n[code example]\n\n**Note**: Numeric fields do not support `index_empty` (empty numeric values are not meaningful)."
    },
    {
      "id": "geo-field-attributes",
      "title": "Geo Field Attributes",
      "role": "content",
      "text": "Geo fields store geographic coordinates for location-based queries.\n\nGeo fields support the common attributes (`sortable`, `no_index`, `index_missing`) but have no geo-specific attributes. The field value should be a string in `\"longitude,latitude\"` format.\n\n[code example]\n\n**Note**: Geo fields do not support `index_empty` (empty coordinates are not meaningful)."
    },
    {
      "id": "vector-field-attributes",
      "title": "Vector Field Attributes",
      "role": "content",
      "text": "Vector fields have a different attribute structure. See [Schema](https://redis.io/docs/latest/../api/schema) for complete vector field documentation.\n\nKey vector attributes:\n\n- `dims`: Vector dimensionality (required)\n- `algorithm`: `flat`, `hnsw`, or `svs-vamana`\n- `distance_metric`: `COSINE`, `L2`, or `IP`\n- `datatype`: Vector precision (see table below)\n- `index_missing`: Allow searching for documents without vectors\n\n[code example]"
    },
    {
      "id": "vector-datatypes",
      "title": "Vector Datatypes",
      "role": "content",
      "text": "The `datatype` attribute controls how vector components are stored. Smaller datatypes reduce memory usage but may affect precision.\n\n| Datatype   |   Bits | Memory (768 dims)   | Use Case                                                                           |\n|------------|--------|---------------------|------------------------------------------------------------------------------------|\n| `float32`  |     32 | 3 KB                | Default. Best precision for most applications.                                     |\n| `float16`  |     16 | 1.5 KB              | Good balance of memory and precision. Recommended for large-scale deployments.     |\n| `bfloat16` |     16 | 1.5 KB              | Better dynamic range than float16. Useful when embeddings have large value ranges. |\n| `float64`  |     64 | 6 KB                | Maximum precision. Rarely needed.                                                  |\n| `int8`     |      8 | 768 B               | Integer quantization. Significant memory savings with some precision loss.         |\n| `uint8`    |      8 | 768 B               | Unsigned integer quantization. For embeddings with non-negative values.            |\n\n**Algorithm Compatibility:**\n\n| Datatype   | FLAT   | HNSW   | SVS-VAMANA   |\n|------------|--------|--------|--------------|\n| `float32`  | Yes    | Yes    | Yes          |\n| `float16`  | Yes    | Yes    | Yes          |\n| `bfloat16` | Yes    | Yes    | No           |\n| `float64`  | Yes    | Yes    | No           |\n| `int8`     | Yes    | Yes    | No           |\n| `uint8`    | Yes    | Yes    | No           |\n\n**Choosing a Datatype:**\n\n- **Start with `float32`** unless you have memory constraints\n- **Use `float16`** for production systems with millions of vectors (50% memory savings, minimal precision loss)\n- **Use `int8`/`uint8`** only after benchmarking recall on your specific dataset\n- **SVS-VAMANA users**: Must use `float16` or `float32`\n\n**Quantization with the Migrator:**\n\nYou can change vector datatypes on existing indexes using the migration wizard:\n\n[code example]\n\nThe migrator automatically re-encodes stored vectors to the new precision. See [Migrate an Index](https://redis.io/docs/latest/../user_guide/how_to_guides/migrate-indexes) for details.\nWhen you apply the resulting migration plan, pass `--backup-dir`; the backup directory is required before any migration starts and stores original vector bytes for resume and rollback."
    },
    {
      "id": "redis-specific-subtleties",
      "title": "Redis-Specific Subtleties",
      "role": "content",
      "text": ""
    },
    {
      "id": "modifier-ordering",
      "title": "Modifier Ordering",
      "role": "content",
      "text": "Redis Search has specific requirements for the order of field modifiers. RedisVL handles this automatically, but it’s useful to understand:\n\n**Canonical order**: `INDEXEMPTY` → `INDEXMISSING` → `SORTABLE` → `UNF` → `NOINDEX`\n\nIf you’re debugging raw Redis commands, ensure modifiers appear in this order."
    },
    {
      "id": "field-type-limitations",
      "title": "Field Type Limitations",
      "role": "content",
      "text": "Not all attributes work with all field types:\n\n| Attribute        | Text   | Tag   | Numeric   | Geo   | Vector   |\n|------------------|--------|-------|-----------|-------|----------|\n| `sortable`       | ✓      | ✓     | ✓         | ✓     | ✗        |\n| `no_index`       | ✓      | ✓     | ✓         | ✓     | ✗        |\n| `index_missing`  | ✓      | ✓     | ✓         | ✓     | ✓        |\n| `index_empty`    | ✓      | ✓     | ✗         | ✗     | ✗        |\n| `unf`            | ✓      | ✗     | ✓         | ✗     | ✗        |\n| `withsuffixtrie` | ✓      | ✓     | ✗         | ✗     | ✗        |"
    },
    {
      "id": "migration-support",
      "title": "Migration Support",
      "role": "content",
      "text": "The migration wizard (`rvl migrate wizard`) supports updating field attributes on existing indexes. The table below shows which attributes can be updated via the wizard vs requiring manual schema patch editing.\n\n**Wizard Prompts:**\n\n| Attribute              | Text     | Tag    | Numeric   | Geo    | Vector   |\n|------------------------|----------|--------|-----------|--------|----------|\n| `sortable`             | Wizard   | Wizard | Wizard    | Wizard | N/A      |\n| `index_missing`        | Wizard   | Wizard | Wizard    | Wizard | N/A      |\n| `index_empty`          | Wizard   | Wizard | N/A       | N/A    | N/A      |\n| `no_index`             | Wizard   | Wizard | Wizard    | Wizard | N/A      |\n| `unf`                  | Wizard\\* | N/A    | Wizard\\*  | N/A    | N/A      |\n| `separator`            | N/A      | Wizard | N/A       | N/A    | N/A      |\n| `case_sensitive`       | N/A      | Wizard | N/A       | N/A    | N/A      |\n| `no_stem`              | Wizard   | N/A    | N/A       | N/A    | N/A      |\n| `weight`               | Wizard   | N/A    | N/A       | N/A    | N/A      |\n| `algorithm`            | N/A      | N/A    | N/A       | N/A    | Wizard   |\n| `datatype`             | N/A      | N/A    | N/A       | N/A    | Wizard   |\n| `distance_metric`      | N/A      | N/A    | N/A       | N/A    | Wizard   |\n| `m`, `ef_construction` | N/A      | N/A    | N/A       | N/A    | Wizard   |\n\n *\\* `unf` is only prompted when `sortable` is enabled.*\n\n**Manual Schema Patch Required:**\n\n| Attribute        | Notes                               |\n|------------------|-------------------------------------|\n| `withsuffixtrie` | Suffix/contains search optimization |\n\n*Note: `phonetic_matcher` is supported by the wizard for text fields.*\n\n**Example manual patch** for adding `index_missing` to a field:\n\n[code example]\n\n[code example]"
    },
    {
      "id": "json-path-for-nested-fields",
      "title": "JSON Path for Nested Fields",
      "role": "content",
      "text": "When using JSON storage, use the `path` attribute to index nested fields:\n\n[code example]\n\nThe `name` becomes the field’s alias in queries, while `path` specifies where to find the data."
    },
    {
      "id": "complete-example",
      "title": "Complete Example",
      "role": "content",
      "text": "[code example]\n\n**Learn more:** [Schema](https://redis.io/docs/latest/../api/schema) provides the complete API reference for all field types and attributes."
    }
  ],
  "examples": [
    {
      "id": "sortable-ex0",
      "language": "yaml",
      "code": "# YAML\n- name: created_at\n  type: numeric\n  attrs:\n    sortable: true",
      "section_id": "sortable"
    },
    {
      "id": "sortable-ex1",
      "language": "python",
      "code": "# Python\n{\"name\": \"created_at\", \"type\": \"numeric\", \"attrs\": {\"sortable\": True}}",
      "section_id": "sortable"
    },
    {
      "id": "no_index-ex0",
      "language": "yaml",
      "code": "# YAML - Store for sorting but don't index for search\n- name: internal_score\n  type: numeric\n  attrs:\n    sortable: true\n    no_index: true",
      "section_id": "no_index"
    },
    {
      "id": "index_missing-ex0",
      "language": "yaml",
      "code": "# YAML\n- name: optional_category\n  type: tag\n  attrs:\n    index_missing: true",
      "section_id": "index_missing"
    },
    {
      "id": "index_missing-ex1",
      "language": "python",
      "code": "# Python\n{\"name\": \"optional_category\", \"type\": \"tag\", \"attrs\": {\"index_missing\": True}}",
      "section_id": "index_missing"
    },
    {
      "id": "index_missing-ex2",
      "language": "python",
      "code": "from redisvl.query.filter import Tag\n\n# Find documents where category is missing\nfilter_expr = Tag(\"optional_category\").ismissing()",
      "section_id": "index_missing"
    },
    {
      "id": "weight-ex0",
      "language": "yaml",
      "code": "- name: title\n  type: text\n  attrs:\n    weight: 2.0  # Title matches count double\n\n- name: description\n  type: text\n  attrs:\n    weight: 1.0  # Default weight",
      "section_id": "weight"
    },
    {
      "id": "no_stem-ex0",
      "language": "yaml",
      "code": "- name: product_code\n  type: text\n  attrs:\n    no_stem: true",
      "section_id": "no_stem"
    },
    {
      "id": "withsuffixtrie-ex0",
      "language": "yaml",
      "code": "- name: email\n  type: text\n  attrs:\n    withsuffixtrie: true",
      "section_id": "withsuffixtrie"
    },
    {
      "id": "phonetic_matcher-ex0",
      "language": "yaml",
      "code": "- name: name\n  type: text\n  attrs:\n    phonetic_matcher: \"dm:en\"  # Double Metaphone, English",
      "section_id": "phonetic_matcher"
    },
    {
      "id": "index_empty-ex0",
      "language": "yaml",
      "code": "- name: middle_name\n  type: text\n  attrs:\n    index_empty: true",
      "section_id": "index_empty"
    },
    {
      "id": "unf-un-normalized-form-ex0",
      "language": "yaml",
      "code": "- name: title\n  type: text\n  attrs:\n    sortable: true\n    unf: true  # Keep original case for sorting",
      "section_id": "unf-un-normalized-form"
    },
    {
      "id": "separator-ex0",
      "language": "yaml",
      "code": "- name: categories\n  type: tag\n  attrs:\n    separator: \"|\"  # Use pipe instead of comma",
      "section_id": "separator"
    },
    {
      "id": "case_sensitive-ex0",
      "language": "yaml",
      "code": "- name: product_sku\n  type: tag\n  attrs:\n    case_sensitive: true",
      "section_id": "case_sensitive"
    },
    {
      "id": "withsuffixtrie-1-ex0",
      "language": "yaml",
      "code": "- name: email_domain\n  type: tag\n  attrs:\n    withsuffixtrie: true",
      "section_id": "withsuffixtrie-1"
    },
    {
      "id": "index_empty-1-ex0",
      "language": "yaml",
      "code": "- name: optional_tags\n  type: tag\n  attrs:\n    index_empty: true",
      "section_id": "index_empty-1"
    },
    {
      "id": "unf-un-normalized-form-1-ex0",
      "language": "yaml",
      "code": "- name: price\n  type: numeric\n  attrs:\n    sortable: true\n    unf: true",
      "section_id": "unf-un-normalized-form-1"
    },
    {
      "id": "geo-field-attributes-ex0",
      "language": "yaml",
      "code": "- name: location\n  type: geo\n  attrs:\n    sortable: true",
      "section_id": "geo-field-attributes"
    },
    {
      "id": "vector-field-attributes-ex0",
      "language": "yaml",
      "code": "- name: embedding\n  type: vector\n  attrs:\n    algorithm: hnsw\n    dims: 768\n    distance_metric: cosine\n    datatype: float32\n    index_missing: true  # Handle documents without embeddings",
      "section_id": "vector-field-attributes"
    },
    {
      "id": "vector-datatypes-ex0",
      "language": "bash",
      "code": "rvl migrate wizard --index my_index --url redis://localhost:6379\n# Select \"Update field\" > choose vector field > change datatype",
      "section_id": "vector-datatypes"
    },
    {
      "id": "migration-support-ex0",
      "language": "yaml",
      "code": "# schema_patch.yaml\nversion: 1\nchanges:\n  update_fields:\n    - name: category\n      attrs:\n        index_missing: true",
      "section_id": "migration-support"
    },
    {
      "id": "migration-support-ex1",
      "language": "bash",
      "code": "rvl migrate plan --index my_index --schema-patch schema_patch.yaml",
      "section_id": "migration-support"
    },
    {
      "id": "json-path-for-nested-fields-ex0",
      "language": "yaml",
      "code": "- name: author_name\n  type: text\n  path: $.metadata.author.name\n  attrs:\n    sortable: true",
      "section_id": "json-path-for-nested-fields"
    },
    {
      "id": "complete-example-ex0",
      "language": "yaml",
      "code": "version: \"0.1.0\"\nindex:\n  name: products\n  prefix: product\n  storage_type: json\n\nfields:\n  # Full-text searchable with high relevance\n  - name: title\n    type: text\n    path: $.title\n    attrs:\n      weight: 2.0\n      sortable: true\n\n  # Exact-match categories\n  - name: category\n    type: tag\n    path: $.category\n    attrs:\n      separator: \"|\"\n      index_missing: true\n\n  # Sortable price with range queries\n  - name: price\n    type: numeric\n    path: $.price\n    attrs:\n      sortable: true\n\n  # Store-only field for sorting\n  - name: internal_rank\n    type: numeric\n    path: $.internal_rank\n    attrs:\n      sortable: true\n      no_index: true\n\n  # Vector embeddings\n  - name: embedding\n    type: vector\n    path: $.embedding\n    attrs:\n      algorithm: hnsw\n      dims: 768\n      distance_metric: cosine\n\n  # Location search\n  - name: store_location\n    type: geo\n    path: $.location",
      "section_id": "complete-example"
    }
  ]
}
