{
  "id": "field-attributes",
  "title": "Field Attributes",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/0.17.0/concepts/field-attributes/",
  "summary": "",
  "content": "\n\nField attributes customize how Redis indexes and searches your data. Each field type has specific attributes that control indexing behavior, search capabilities, and storage options.\n\n## Common Attributes\n\nThese attributes are available on most non-vector field types (text, tag, numeric, geo).\n\n### sortable\n\nEnables 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```yaml\n# YAML\n- name: created_at\n  type: numeric\n  attrs:\n    sortable: true\n```\n\n```python\n# Python\n{\"name\": \"created_at\", \"type\": \"numeric\", \"attrs\": {\"sortable\": True}}\n```\n\n**Use when**: You need to sort search results by this field (e.g., \"newest first\", \"highest price\").\n\n### no_index\n\nStores 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```yaml\n# 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\n```\n\n**Use when**: You want to sort by a field but never filter on it, saving index space.\n\n### index_missing\n\nAllows 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```yaml\n# YAML\n- name: optional_category\n  type: tag\n  attrs:\n    index_missing: true\n```\n\n```python\n# Python\n{\"name\": \"optional_category\", \"type\": \"tag\", \"attrs\": {\"index_missing\": True}}\n```\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```python\nfrom redisvl.query.filter import Tag\n\n# Find documents where category is missing\nfilter_expr = Tag(\"optional_category\").ismissing()\n```\n\n## Text Field Attributes\n\nText fields support full-text search with these additional attributes.\n\n### weight\n\nControls the importance of this field in relevance scoring. Higher weights make matches in this field rank higher.\n\n```yaml\n- 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\n```\n\n**Use when**: Some text fields are more important than others for search relevance.\n\n### no_stem\n\nDisables stemming for this field. By default, Redis applies stemming so \"running\" matches \"run\". Disable when exact word forms matter.\n\n```yaml\n- name: product_code\n  type: text\n  attrs:\n    no_stem: true\n```\n\n**Use when**: Field contains codes, identifiers, or technical terms where stemming would cause incorrect matches.\n\n### withsuffixtrie\n\nMaintains a suffix trie for optimized suffix and contains queries. Enables efficient `*suffix` and `*contains*` searches.\n\n```yaml\n- name: email\n  type: text\n  attrs:\n    withsuffixtrie: true\n```\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.\n\n### phonetic_matcher\n\nEnables phonetic matching using the specified algorithm. Matches words that sound similar.\n\n```yaml\n- name: name\n  type: text\n  attrs:\n    phonetic_matcher: \"dm:en\"  # Double Metaphone, English\n```\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\").\n\n### index_empty\n\nAllows indexing and searching for empty strings. By default, empty strings are not indexed.\n\n```yaml\n- name: middle_name\n  type: text\n  attrs:\n    index_empty: true\n```\n\n**Use when**: Empty string is a meaningful value you need to query for.\n\n### unf (Un-Normalized Form)\n\nPreserves 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```yaml\n- name: title\n  type: text\n  attrs:\n    sortable: true\n    unf: true  # Keep original case for sorting\n```\n\n**Use when**: You need case-sensitive sorting or must preserve exact original values.\n\n## Tag Field Attributes\n\nTag fields are for exact-match filtering on categorical data.\n\n### separator\n\nSpecifies the character that separates multiple tags in a single field value. Default is comma (`,`).\n\n```yaml\n- name: categories\n  type: tag\n  attrs:\n    separator: \"|\"  # Use pipe instead of comma\n```\n\n**Use when**: Your tag values contain commas, or you’re using a different delimiter in your data.\n\n### case_sensitive\n\nMakes tag matching case-sensitive. By default, tags are lowercased for matching.\n\n```yaml\n- name: product_sku\n  type: tag\n  attrs:\n    case_sensitive: true\n```\n\n**Use when**: Tag values are case-sensitive identifiers (SKUs, codes, etc.).\n\n### withsuffixtrie\n\nSame as text fields—enables efficient suffix and contains queries on tags.\n\n```yaml\n- name: email_domain\n  type: tag\n  attrs:\n    withsuffixtrie: true\n```\n\n### index_empty\n\nAllows indexing empty tag values.\n\n```yaml\n- name: optional_tags\n  type: tag\n  attrs:\n    index_empty: true\n```\n\n## Numeric Field Attributes\n\nNumeric fields support range queries and sorting.\n\n### unf (Un-Normalized Form)\n\nFor sortable numeric fields, preserves the exact numeric representation without normalization.\n\n**Requires**: `sortable: true`\n\n```yaml\n- name: price\n  type: numeric\n  attrs:\n    sortable: true\n    unf: true\n```\n\n**Note**: Numeric fields do not support `index_empty` (empty numeric values are not meaningful).\n\n## Geo Field Attributes\n\nGeo 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```yaml\n- name: location\n  type: geo\n  attrs:\n    sortable: true\n```\n\n**Note**: Geo fields do not support `index_empty` (empty coordinates are not meaningful).\n\n## Vector Field Attributes\n\nVector fields have a different attribute structure. See [Schema](../api/schema.md) 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`: `float16`, `float32`, `float64`, or `bfloat16`\n- `index_missing`: Allow searching for documents without vectors\n\n```yaml\n- 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\n```\n\n## Redis-Specific Subtleties\n\n### Modifier Ordering\n\nRedis 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.\n\n### Field Type Limitations\n\nNot 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` | ✓      | ✓     | ✗         | ✗     | ✗        |\n\n### JSON Path for Nested Fields\n\nWhen using JSON storage, use the `path` attribute to index nested fields:\n\n```yaml\n- name: author_name\n  type: text\n  path: $.metadata.author.name\n  attrs:\n    sortable: true\n```\n\nThe `name` becomes the field’s alias in queries, while `path` specifies where to find the data.\n\n## Complete Example\n\n```yaml\nversion: \"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\n```\n\n**Learn more:** [Schema](../api/schema.md) provides the complete API reference for all field types and attributes.\n",
  "tags": [],
  "last_updated": "2026-04-21T14:39:33+02:00"
}
