@@ -591,7 +591,7 @@ else if (fieldType == Point.class) {
591591 field .getName () :
592592 String .join ("." , prefix , field .getName ());
593593
594- // For nested fields, automatically create index fields even without explicit annotations
594+ // For nested fields, automatically create index fields when the parent field is annotated with @Indexed(schemaFieldType = SchemaFieldType.NESTED)
595595 fields .addAll (createNestedIndexFields (field , subfield , subfieldPrefix , isDocument ));
596596 }
597597 }
@@ -887,6 +887,32 @@ private List<SearchField> getNestedField(String fieldPrefix, java.lang.reflect.F
887887 return fieldList ;
888888 }
889889
890+ /**
891+ * Determines the appropriate FieldType for a given Java class.
892+ * This utility method centralizes the logic for mapping Java types to Redis field types.
893+ */
894+ private enum FieldTypeMapper {
895+ TAG ,
896+ NUMERIC ,
897+ GEO ,
898+ UNSUPPORTED ;
899+
900+ static FieldTypeMapper getFieldType (Class <?> fieldType ) {
901+ if (CharSequence .class .isAssignableFrom (
902+ fieldType ) || fieldType == Boolean .class || fieldType == UUID .class || fieldType == Ulid .class || fieldType
903+ .isEnum ()) {
904+ return TAG ;
905+ } else if (Number .class .isAssignableFrom (
906+ fieldType ) || fieldType == LocalDateTime .class || fieldType == LocalDate .class || fieldType == Date .class || fieldType == Instant .class || fieldType == OffsetDateTime .class ) {
907+ return NUMERIC ;
908+ } else if (fieldType == Point .class ) {
909+ return GEO ;
910+ } else {
911+ return UNSUPPORTED ;
912+ }
913+ }
914+ }
915+
890916 /**
891917 * Creates index fields for nested array elements automatically.
892918 * This method handles automatic indexing of all fields within nested objects
@@ -900,62 +926,48 @@ private List<SearchField> createNestedIndexFields(java.lang.reflect.Field arrayF
900926
901927 // For nested arrays, the path should be: $.arrayField[*].nestedField
902928 // The prefix already contains the array field name, so we just need [*].nestedField
929+ // JSON documents use a "$" prefix to denote the root of the document, while hash structures do not.
930+ // The `isDocument` flag determines whether the entity is stored as a JSON document or a hash structure in Redis.
931+ // This affects the field path format: JSON documents require "$." as the prefix, while hash structures do not.
903932 String fullFieldPath = isDocument ?
904933 "$." + arrayField .getName () + "[*]." + nestedField .getName () :
905934 arrayField .getName () + "[*]." + nestedField .getName ();
906935
907936 logger .info (String .format ("Creating automatic nested field index: %s -> %s" , arrayField .getName (), fullFieldPath ));
908937
909938 // Determine field type and create appropriate index field
910- if (CharSequence .class .isAssignableFrom (
911- nestedFieldType ) || nestedFieldType == Boolean .class || nestedFieldType == UUID .class || nestedFieldType == Ulid .class ) {
912-
913- // Create TAG field for strings, booleans, UUIDs, and ULIDs
914- FieldName fieldName = FieldName .of (fullFieldPath );
915- String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
916- if (alias != null && !alias .isEmpty ()) {
917- fieldName = fieldName .as (alias );
918- }
919-
920- fields .add (SearchField .of (arrayField , getTagField (fieldName , "|" , false )));
921-
922- } else if (Number .class .isAssignableFrom (
923- nestedFieldType ) || nestedFieldType == LocalDateTime .class || nestedFieldType == LocalDate .class || nestedFieldType == Date .class || nestedFieldType == Instant .class || nestedFieldType == OffsetDateTime .class ) {
924-
925- // Create NUMERIC field for numbers and dates
926- FieldName fieldName = FieldName .of (fullFieldPath );
927- String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
928- if (alias != null && !alias .isEmpty ()) {
929- fieldName = fieldName .as (alias );
939+ FieldTypeMapper fieldTypeMapper = FieldTypeMapper .getFieldType (nestedFieldType );
940+
941+ switch (fieldTypeMapper ) {
942+ case TAG -> {
943+ // Create TAG field for strings, booleans, UUIDs, ULIDs, and enums
944+ FieldName fieldName = FieldName .of (fullFieldPath );
945+ String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
946+ if (alias != null && !alias .isEmpty ()) {
947+ fieldName = fieldName .as (alias );
948+ }
949+ fields .add (SearchField .of (arrayField , getTagField (fieldName , "|" , false )));
930950 }
931-
932- fields .add (SearchField .of (arrayField , NumericField .of (fieldName )));
933-
934- } else if (nestedFieldType == Point .class ) {
935-
936- // Create GEO field for Point objects
937- FieldName fieldName = FieldName .of (fullFieldPath );
938- String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
939- if (alias != null && !alias .isEmpty ()) {
940- fieldName = fieldName .as (alias );
951+ case NUMERIC -> {
952+ // Create NUMERIC field for numbers and dates
953+ FieldName fieldName = FieldName .of (fullFieldPath );
954+ String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
955+ if (alias != null && !alias .isEmpty ()) {
956+ fieldName = fieldName .as (alias );
957+ }
958+ fields .add (SearchField .of (arrayField , NumericField .of (fieldName )));
941959 }
942-
943- fields .add (SearchField .of (arrayField , GeoField .of (fieldName )));
944-
945- } else if (nestedFieldType .isEnum ()) {
946-
947- // Create TAG field for enums
948- FieldName fieldName = FieldName .of (fullFieldPath );
949- String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
950- if (alias != null && !alias .isEmpty ()) {
951- fieldName = fieldName .as (alias );
960+ case GEO -> {
961+ // Create GEO field for Point objects
962+ FieldName fieldName = FieldName .of (fullFieldPath );
963+ String alias = QueryUtils .searchIndexFieldAliasFor (nestedField , prefix );
964+ if (alias != null && !alias .isEmpty ()) {
965+ fieldName = fieldName .as (alias );
966+ }
967+ fields .add (SearchField .of (arrayField , GeoField .of (fieldName )));
952968 }
953-
954- fields .add (SearchField .of (arrayField , getTagField (fieldName , "|" , false )));
955-
956- } else {
957- logger .debug (String .format ("Skipping nested field %s of unsupported type %s" , nestedField .getName (),
958- nestedFieldType .getSimpleName ()));
969+ case UNSUPPORTED -> logger .debug (String .format ("Skipping nested field %s of unsupported type %s" , nestedField
970+ .getName (), nestedFieldType .getSimpleName ()));
959971 }
960972
961973 return fields ;
0 commit comments