ElasticSearch returning all Field values as null

1.3k views Asked by At

My config:

@Configuration
@EnableElasticsearchRepositories(
    basePackages = { "com.aj.new.repositories" })
public class ElasticDataSourceConfig {

    @Bean
    public RestHighLevelClient client() {

        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
            .connectedTo("localhost:9200")
            .build();

        return RestClients.create(clientConfiguration).rest();
    }

    @Bean
    public ElasticsearchRestTemplate elasticsearchTemplate() {
        return new ElasticsearchRestTemplate(client());
    }
}

Document:

@Document(indexName = "provider_search")
public class Provider {

    @Id @Field
    private Long id;

    @Field(type = FieldType.Keyword)
    private String search;

    @Field(name = "ProviderName", type = FieldType.Keyword)
    private String providerName;

    @Field(name = "Address")
    private String address;

    @Field(name = "City")
    private String city;

    @Field(name = "State")
    private String state;

   ...getters...
   ...setters...
}

Usage:

@Service
public class MySearchService {
    
  @Autowired
  private ElasticsearchRestTemplate elasticsearchRestTemplate;

  public List<Provider> searchProvidersUsingElastic(final String 
    providerName, final AddressSearchCriteriaBean addressCriteria) {

    final NativeSearchQueryBuilder searchQueryBuilder = new 
      NativeSearchQueryBuilder();
    
    if (providerName != null) {
      final String regex = ".*" + providerName + ".*";
      searchQueryBuilder.withQuery(regexpQuery("providerName", regex));
    }
    
    if (addressCriteria.getState() != null) {
      searchQueryBuilder.withFilter(matchQuery("state", 
        addressCriteria.getState())
       .fuzziness(Fuzziness.ONE));
    }   
    
    SearchHits<Provider> articles = 
      elasticsearchRestTemplate.search(searchQueryBuilder.build(), 
      Provider.class, IndexCoordinates.of("provider_search"));
    
    final List<Provider> providers = articles
      .stream()
      .map(SearchHit::getContent)
      .collect(Collectors.toList());
    
    return providers;
  }
}

When debugging with or without filters, I get providers with only their ID field populated. Every other field like "search", "state", etc. is null.

This is my first venture in ElasticSearch world and I'm not sure what's wrong here. Any help is appreciated.

Edit:

Provider Mappings from Elasticsearch

{
  "provider_search": {
    "mappings": {
      "properties": {
        "Address": {
          "type": "text",
          "analyzer": "autocomplete"
        },
        "City": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "FaxNumber": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "PhoneNumber": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "ProviderName": {
          "type": "text",
          "analyzer": "autocomplete"
        },
        "State": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "Status": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "Zip": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "fac_dbk": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "search": {
          "type": "text",
          "analyzer": "autocomplete"
        }
      }
    }
  }
}

Please note that for testing purposes, I have not mapped every field of Provider on Java side. If that's problematic, let me know.

Second Update:

I have changed the Provider document to map the Field names as is. Still, everything except id is still null.

@Document(indexName = "provider_search")
    public class Provider {
    
        @Id
        private Long id;
    
        private String search;
    
        private String ProviderName;
    
        private String Address;
    
        private String City;
    
        private String State;
    
       ...getters...
       ...setters...
    }

UPDATE:

Turns out the Elasticsearch index had a bug and the fields I had mapped on the Java side were not available on the ES index. It has been fixed and I'm seeing all the values populate correctly.

1

There are 1 answers

3
P.J.Meisch On

You have an inconsistency in using the property names (the properties of the Provider entity) and the corresponding field names (the names in Elasticsearch).

Your properties start with a lowercase letter and then are camelcase (providerName, state), for Spring Data Elasticsearch you define them to map to versions starting with a uppercase letter (ProviderName, State) with the @Field annotations. So Spring Data Elasticsearch expects Elasticsearch to return a value for ProviderName and will then store this in the providerName property.

Are the field names in your index starting with an uppercase letter? What does http://localhost:9200/provider_search/_mappings show? This is a guess, as you did not show what Elasticsearch returns, but would explain your error.