2
votes

I am here to implement basic elastic search functionality. I went through few examples but could not figure out what might have went wrong. Application builds fine but returns empty results..

Let me know if you find anything wrong in my configurations or search retrieval..

ElasticSearch config:

@Configuration
@EnableElasticsearchRepositories(basePackages = "challenge.repository")
public class ElasticConfiguration {


    @Bean
    public NodeBuilder nodeBuilder() {
        return new NodeBuilder();
    }

    @Bean
    public ElasticsearchOperations elasticsearchTemplate() throws IOException {
        File tmpDir = File.createTempFile("elastic", Long.toString(System.nanoTime()));
        System.out.println("Temp directory: " + tmpDir.getAbsolutePath());
        Settings.Builder elasticsearchSettings =
                Settings.settingsBuilder()
                        .put("http.enabled", "true") // 1
                        .put("index.number_of_shards", "1")
                        .put("path.data", new File(tmpDir, "data").getAbsolutePath()) // 2
                        .put("path.logs", new File(tmpDir, "logs").getAbsolutePath()) // 2
                        .put("path.work", new File(tmpDir, "work").getAbsolutePath()) // 2
                        .put("path.home", tmpDir); // 3



        return new ElasticsearchTemplate(nodeBuilder()
                .local(true)
                .settings(elasticsearchSettings.build())
                .node()
                .client());
    }
}

As I am trying to search the content that matches in-between text, below is the SearchQueryBuilder I implemented:

@Component
public class MessageSearchQueryBuilder {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    public List<Messages> getAllMessages(String text) {

        QueryBuilder query = QueryBuilders.boolQuery()
                .should(
                        QueryBuilders.queryStringQuery(text)
                                .lenient(true)
                                .field("content")
                ).should(QueryBuilders.queryStringQuery("*" + text + "*")
                        .lenient(true)
                        .field("content"));

        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(query)
                .build();

        List<Messages> messages = elasticsearchTemplate.queryForList(build, Messages.class);

        return messages;
    }

}

Below is the Loader class that loads the data into repository:

@Component
public class MessageLoader {

    @Autowired
    ElasticsearchOperations operations;

    @Autowired
    MessagesRepository messagesRepository;

    @Autowired
    MessageServiceImpl messageServiceImpl;

    @PostConstruct
    @Transactional
    public void loadAll(){

        operations.putMapping(Messages.class);
        System.out.println("Loading Data");
        messagesRepository.save(getData());
        System.out.println(getData());
        System.out.printf("Loading Completed");

    }

    private List<Messages> getData() {
//      Principal principal = SecurityContextHolder.getContext().getAuthentication();
        return messageServiceImpl.getMyMessagesForSearch(2);//Integer.valueOf(principal.getName()));
    }
}

Messages model:

@Document(indexName = "messages", type = "messages", shards = 1)
public class Messages {
    @Id
    private int id;
    private int personId;
    private String content;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getPersonId() {
        return personId;
    }
    public void setPersonId(int personId) {
        this.personId = personId;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Messages [id=" + id + ", personId=" + personId + ", content="
                + content + "]";
    }
}

I have the method called findByContent but I am not using this anywhere as I have my own searchQueryBuilder.. Is this something wrong?

Below is my repository:

public interface MessagesRepository extends ElasticsearchRepository<Messages, Long>  {
    List<Messages> findByContent(String text);
}

Below is my restAPI which retrieves the search results:

@RestController
@RequestMapping("/rest/api/1.0/messages/search")
public class MessageSearchController {
    @Autowired
    private MessageSearchQueryBuilder messageSearchQueryBuilder;

    @GetMapping(value = "/{text}", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<Messages> getAllMessages(@PathVariable final String text) {
        return messageSearchQueryBuilder.getAllMessages(text);
    }
}

I am not finding any clue what I have made wrong in getting the matching search results. Any help is like gods gift.

1
Did you have a chance to resolve this? - Same issue.user

1 Answers

0
votes

In my case the problem was document type specified in @Document annotation. Make sure if it fits to one returned by Elasticsearch. If you not specify type of your documents, the default one is _doc. So for default type your annotation should look like this

@Document(indexName = "messages", type = "_doc", shards = 1)

To quick check type of your documents you can query Elasticsearch by curl, postman or other HTTP client (e.g. to get all documents: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html)