Commit 4ca92206 authored by Exbrayat Cédric's avatar Exbrayat Cédric
Browse files

feat(search): search api endpoint

parent 79dd3a4d
package fr.inra.urgi.rare.dto;
import java.util.List;
import org.springframework.data.domain.Page;
/**
* A page of data
*
* @param <T> the type of data in this page
*/
public final class PageDTO<T> {
/**
* The elements in this page. Its size is less than or equal to {@link #size}
*/
private final List<T> content;
/**
* The number of this page, starting from 0
*/
private final int number;
/**
* The size of a page
*/
private final int size;
/**
* The total number of elements
*/
private final long totalElements;
/**
* The total number of pages
*/
private final int totalPages;
public PageDTO(List<T> content, int number, int size, long totalElements, int totalPages) {
this.content = content;
this.number = number;
this.size = size;
this.totalElements = totalElements;
this.totalPages = totalPages;
}
public static <T> PageDTO<T> fromPage(Page<T> page) {
return new PageDTO<>(page.getContent(),
page.getNumber(),
page.getSize(),
page.getTotalElements(),
page.getTotalPages());
}
public List<T> getContent() {
return content;
}
public int getNumber() {
return number;
}
public int getSize() {
return size;
}
public long getTotalElements() {
return totalElements;
}
public int getTotalPages() {
return totalPages;
}
}
package fr.inra.urgi.rare.search;
import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import fr.inra.urgi.rare.dao.GeneticResourceDao;
import fr.inra.urgi.rare.domain.GeneticResource;
import fr.inra.urgi.rare.dto.PageDTO;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* A REST controller for the search API
*/
@RestController
@RequestMapping("/api/genetic-resources")
public class SearchController {
/**
* Contains the fields searchable on a {@link GeneticResource}.
* This is basically all fields at the exception of a few ones like `identifier`,
* and the ones containing a URL.
*/
private final Set<String> searchableFields = Stream.of(
"name",
"description",
"pillarName",
"databaseSource",
"domain",
"taxon",
"family",
"genus",
"species",
"materialType",
"biotopeType",
"countryOfOrigin",
"countryOfCollect"
).collect(Collectors.toSet());
private GeneticResourceDao geneticResourceDao;
public SearchController(GeneticResourceDao geneticResourceDao) {
this.geneticResourceDao = geneticResourceDao;
}
@GetMapping
public PageDTO<GeneticResource> search(@RequestParam("query") String query) {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(multiMatchQuery(query, searchableFields.toArray(new String[0])))
.build();
Page<GeneticResource> geneticResources = geneticResourceDao.search(searchQuery);
return PageDTO.fromPage(geneticResources);
}
}
package fr.inra.urgi.rare.search;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.List;
import fr.inra.urgi.rare.dao.GeneticResourceDao;
import fr.inra.urgi.rare.domain.GeneticResource;
import fr.inra.urgi.rare.domain.GeneticResourceBuilder;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
/**
* MVC tests for {@link SearchController}
*/
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = SearchController.class)
class SearchControllerTest {
@MockBean
private GeneticResourceDao geneticResourceDao;
@Autowired
private MockMvc mockMvc;
@Test
void shouldSearch() throws Exception {
GeneticResource resource = new GeneticResourceBuilder()
.withId("CFBP 8402")
.withName("CFBP 8402")
.withDescription("Xylella fastidiosa subsp. Pauca, risk group = Quarantine")
.build();
List<GeneticResource> geneticResources = Lists.newArrayList(resource);
Page<GeneticResource> searchResults = new PageImpl<>(geneticResources);
when(geneticResourceDao.search(any(SearchQuery.class))).thenReturn(searchResults);
mockMvc.perform(get("/api/genetic-resources?query=Bacteria"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.totalElements").value(1))
.andExpect(jsonPath("$.content[0].identifier").value(resource.getId()))
.andExpect(jsonPath("$.content[0].name").value(resource.getName()));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment