Commit 33f4ea93 authored by Matija Obreza's avatar Matija Obreza

Merge branch 'ui-252-explore-filter-suggestions-' into 'master'

Ui 252 explore filter suggestions

See merge request genesys-pgr/genesys-server!373
parents 33fb990e 0f517feb
...@@ -46,13 +46,13 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> { ...@@ -46,13 +46,13 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> {
public PartnerFilter owner; public PartnerFilter owner;
/** The accession reference. */ /** The accession reference. */
public AccessionRefFilter accessionRef; public AccessionRefFilter accessionRefs;
/** Dataset location filter */ /** Dataset location filter */
public DatasetLocationFilter location; public DatasetLocationFilter locations;
/** Descriptor filter */ /** Descriptor filter */
public DescriptorFilter descriptor; public DescriptorFilter descriptors;
/** The title. */ /** The title. */
public StringFilter title; public StringFilter title;
...@@ -67,7 +67,7 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> { ...@@ -67,7 +67,7 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> {
public Set<PublishState> state; public Set<PublishState> state;
/** The crop. */ /** The crop. */
public Set<String> crop; public Set<String> crops;
public Set<String> rights; public Set<String> rights;
...@@ -92,21 +92,21 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> { ...@@ -92,21 +92,21 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> {
if (owner != null) { if (owner != null) {
and.and(owner.buildQuery(dataset.owner)); and.and(owner.buildQuery(dataset.owner));
} }
if (accessionRef != null) { if (accessionRefs != null) {
and.and(accessionRef.buildQuery(dataset.accessionRefs)); and.and(accessionRefs.buildQuery(dataset.accessionRefs));
} }
if (descriptor != null) { if (descriptors != null) {
and.and(descriptor.buildQuery(dataset.descriptors.any())); and.and(descriptors.buildQuery(dataset.descriptors.any()));
} }
if (CollectionUtils.isNotEmpty(language)) { if (CollectionUtils.isNotEmpty(language)) {
and.and(dataset.language.in(language)); and.and(dataset.language.in(language));
} }
if (crop != null && !crop.isEmpty()) { if (crops != null && !crops.isEmpty()) {
and.and(dataset.crops.any().in(crop)); and.and(dataset.crops.any().in(crops));
} }
if (location != null) { if (locations != null) {
and.and(location.buildQuery(dataset.locations.any())); and.and(locations.buildQuery(dataset.locations.any()));
} }
if (CollectionUtils.isNotEmpty(rights)) { if (CollectionUtils.isNotEmpty(rights)) {
......
...@@ -20,17 +20,17 @@ public class DatasetLocationFilter extends UuidModelFilter<DatasetLocationFilter ...@@ -20,17 +20,17 @@ public class DatasetLocationFilter extends UuidModelFilter<DatasetLocationFilter
/** /**
* The longitude. * The longitude.
*/ */
public NumberFilter<Double> longitude; public NumberFilter<Double> decimalLongitude;
/** /**
* The latitude. * The latitude.
*/ */
public NumberFilter<Double> latitude; public NumberFilter<Double> decimalLatitude;
/** /**
* The elevation. * The elevation.
*/ */
public Set<String> country; public Set<String> userCountry;
/** /**
...@@ -52,14 +52,14 @@ public class DatasetLocationFilter extends UuidModelFilter<DatasetLocationFilter ...@@ -52,14 +52,14 @@ public class DatasetLocationFilter extends UuidModelFilter<DatasetLocationFilter
final BooleanBuilder and = new BooleanBuilder(); final BooleanBuilder and = new BooleanBuilder();
super.buildQuery(datasetLocation, datasetLocation._super, and); super.buildQuery(datasetLocation, datasetLocation._super, and);
if (longitude != null) { if (decimalLongitude != null) {
and.and(longitude.buildQuery(datasetLocation.decimalLongitude)); and.and(decimalLongitude.buildQuery(datasetLocation.decimalLongitude));
} }
if (latitude != null) { if (decimalLatitude != null) {
and.and(latitude.buildQuery(datasetLocation.decimalLatitude)); and.and(decimalLatitude.buildQuery(datasetLocation.decimalLatitude));
} }
if (CollectionUtils.isNotEmpty(country)) { if (CollectionUtils.isNotEmpty(userCountry)) {
and.and(datasetLocation.userCountry.in(country)); and.and(datasetLocation.userCountry.in(userCountry));
} }
return and; return and;
......
...@@ -86,7 +86,7 @@ public class DescriptorFilter extends UuidModelFilter<DescriptorFilter, Descript ...@@ -86,7 +86,7 @@ public class DescriptorFilter extends UuidModelFilter<DescriptorFilter, Descript
public NumberFilter<Double> maxValue; public NumberFilter<Double> maxValue;
/** Descriptor list filter */ /** Descriptor list filter */
public DescriptorListFilter list; public DescriptorListFilter descriptorLists;
/** Descriptor is in use: referenced in Dataset or DescriptorList. */ /** Descriptor is in use: referenced in Dataset or DescriptorList. */
public Boolean used; public Boolean used;
...@@ -146,8 +146,8 @@ public class DescriptorFilter extends UuidModelFilter<DescriptorFilter, Descript ...@@ -146,8 +146,8 @@ public class DescriptorFilter extends UuidModelFilter<DescriptorFilter, Descript
if (maxValue != null) { if (maxValue != null) {
and.and(maxValue.buildQuery(descriptorPath.maxValue)); and.and(maxValue.buildQuery(descriptorPath.maxValue));
} }
if (list != null) { if (descriptorLists != null) {
and.and(list.buildQuery(descriptorPath.descriptorLists.any())); and.and(descriptorLists.buildQuery(descriptorPath.descriptorLists.any()));
} }
if (used != null) { if (used != null) {
if (used.booleanValue()==true) { if (used.booleanValue()==true) {
......
...@@ -23,6 +23,7 @@ import java.io.OutputStream; ...@@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -30,6 +31,7 @@ import java.util.UUID; ...@@ -30,6 +31,7 @@ import java.util.UUID;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.model.JsonViews; import org.genesys.blocks.model.JsonViews;
import org.genesys.catalog.service.ShortFilterService; import org.genesys.catalog.service.ShortFilterService;
...@@ -185,6 +187,34 @@ public class AccessionController { ...@@ -185,6 +187,34 @@ public class AccessionController {
return new FilteredPage<>(filterInfo.filterCode, filterInfo.filter, accessionService.list(filterInfo.filter, page.toPageRequest(100, Sort.Direction.ASC, "seqNo"))); return new FilteredPage<>(filterInfo.filterCode, filterInfo.filter, accessionService.list(filterInfo.filter, page.toPageRequest(100, Sort.Direction.ASC, "seqNo")));
} }
/**
* List accessions by filterCode or filter
*
* @param page the page
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws IOException
*/
@PostMapping(value = "/filter", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public AccessionSuggestionPage listSuggestions(@RequestParam(name = "f", required = false) String filterCode, final Pagination page,
@RequestBody(required = false) AccessionFilter filter) throws IOException, SearchException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
FilterInfo<AccessionFilter> filterInfo = shortFilterService.processFilter(filterCode, filter, AccessionFilter.class);
FilteredPage<Accession> pageRes = new FilteredPage<>(filterInfo.filterCode, filterInfo.filter, accessionService.list(filterInfo.filter, page.toPageRequest(100, Sort.Direction.ASC, "seqNo")));
Map<String, TermResult> suggestionRes = accessionService.getSuggestions(filter);
return AccessionSuggestionPage.from(pageRes, suggestionRes);
}
/** /**
* Get term overview for filters * Get term overview for filters
* *
...@@ -206,8 +236,9 @@ public class AccessionController { ...@@ -206,8 +236,9 @@ public class AccessionController {
Map<String, TermResult> overview = elasticsearchService.termStatisticsAuto(Accession.class, filter, 10, terms.toArray(new String[] {})); Map<String, TermResult> overview = elasticsearchService.termStatisticsAuto(Accession.class, filter, 10, terms.toArray(new String[] {}));
long accessionCount = accessionService.countAccessions(filter); long accessionCount = accessionService.countAccessions(filter);
Map<String, TermResult> suggestions = accessionService.getSuggestions(filter);
return AccessionOverview.from(filterCode, filter, overview, accessionCount); return AccessionOverview.from(filterCode, filter, overview, accessionCount, suggestions);
} }
/** /**
...@@ -264,7 +295,7 @@ public class AccessionController { ...@@ -264,7 +295,7 @@ public class AccessionController {
@PostMapping(value = "/mapinfo", produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/mapinfo", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView({ JsonViews.Public.class }) @JsonView({ JsonViews.Public.class })
public AccessionMapInfo mapInfo(@RequestParam(value = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter) throws IOException { public AccessionMapInfo mapInfo(@RequestParam(value = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter) throws IOException, SearchException {
if (filterCode != null) { if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class); filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else { } else {
...@@ -282,6 +313,7 @@ public class AccessionController { ...@@ -282,6 +313,7 @@ public class AccessionController {
} }
mapInfo.accessionCount = accessionService.countAccessions(filter); mapInfo.accessionCount = accessionService.countAccessions(filter);
mapInfo.tileServers = cdnServers; mapInfo.tileServers = cdnServers;
mapInfo.suggestions= accessionService.getSuggestions(filter);
return mapInfo; return mapInfo;
} }
...@@ -338,64 +370,6 @@ public class AccessionController { ...@@ -338,64 +370,6 @@ public class AccessionController {
return geoJson; return geoJson;
} }
/**
* Get term overview for filters
*
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws SearchException
*/
@PostMapping(value = "/filter-suggest", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public Map<String, TermResult> filterSuggestions(@RequestParam(name = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter)
throws IOException, SearchException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
Map<String, TermResult> termResults = elasticsearchService.termStatisticsAuto(Accession.class, filter, 10, terms.toArray(new String[] {}));
// "institute.code", "institute.country.code3", "cropName", "crop.shortName",
// "taxonomy.genus", "taxonomy.genusSpecies", "taxonomy.species",
// "countryOfOrigin.code3", "sampStat", "available", "mlsStatus", "donorCode",
// "sgsv", "storage", "duplSite", "breederCode"
if (filter.taxa != null) {
if (CollectionUtil.isNotEmpty(filter.taxa.species)) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.taxa.species.clear();
termResults.put("taxonomy.species", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "taxonomy.species"));
}
if (CollectionUtil.isNotEmpty(filter.taxa.genus)) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.taxa.genus.clear();
termResults.put("taxonomy.genus", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "taxonomy.genus"));
}
}
if (filter.origin != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.origin = null;
termResults.put("countryOfOrigin.code3", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "countryOfOrigin.code3"));
}
if (filter.holder != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.holder = null;
termResults.putAll(elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "institute.code", "institute.country.code3"));
}
if (filter.crop != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.crop = null;
termResults.putAll(elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "cropName", "crop.shortName"));
}
return termResults;
}
private AccessionFilter copyFilter(AccessionFilter filter) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException { private AccessionFilter copyFilter(AccessionFilter filter) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
return objectMapper.readValue(objectMapper.writeValueAsString(filter), AccessionFilter.class); return objectMapper.readValue(objectMapper.writeValueAsString(filter), AccessionFilter.class);
} }
...@@ -548,6 +522,7 @@ public class AccessionController { ...@@ -548,6 +522,7 @@ public class AccessionController {
public Number[][] bounds; public Number[][] bounds;
public long accessionCount; public long accessionCount;
public String[] tileServers; public String[] tileServers;
public Map<String, TermResult> suggestions;
} }
public static class AccessionOverview { public static class AccessionOverview {
...@@ -555,16 +530,33 @@ public class AccessionController { ...@@ -555,16 +530,33 @@ public class AccessionController {
public AccessionFilter filter; public AccessionFilter filter;
public long accessionCount; public long accessionCount;
public Map<String, TermResult> overview; public Map<String, TermResult> overview;
public Map<String, TermResult> suggestions;
private static AccessionOverview from(String filterCode, AccessionFilter filter, Map<String, TermResult> overview, long accessionCount) { private static AccessionOverview from(String filterCode, AccessionFilter filter, Map<String, TermResult> overview, long accessionCount, Map<String, TermResult> suggestions) {
AccessionOverview res = new AccessionOverview(); AccessionOverview res = new AccessionOverview();
res.filterCode = filterCode; res.filterCode = filterCode;
res.filter = filter; res.filter = filter;
res.overview = overview; res.overview = overview;
res.accessionCount = accessionCount; res.accessionCount = accessionCount;
res.suggestions = suggestions;
return res; return res;
} }
} }
public static class AccessionSuggestionPage {
@JsonUnwrapped
public FilteredPage<Accession> page;
public Map<String, TermResult> suggestions;
private static AccessionSuggestionPage from(FilteredPage<Accession> page, Map<String, TermResult> suggestions) {
AccessionSuggestionPage res = new AccessionSuggestionPage();
res.page = page;
res.suggestions = suggestions;
return res;
}
}
} }
...@@ -106,8 +106,8 @@ public class SearchController extends ApiBaseController { ...@@ -106,8 +106,8 @@ public class SearchController extends ApiBaseController {
return null; return null;
} }
BoolQueryBuilder q = boolQuery(); BoolQueryBuilder q = boolQuery();
if (filters.crop != null && !filters.crop.isEmpty()) { if (filters.crops != null && !filters.crops.isEmpty()) {
q.must(termsQuery("crop", filters.crop)); q.must(termsQuery("crop", filters.crops));
} }
q.boost(3.0f); q.boost(3.0f);
......
...@@ -38,6 +38,7 @@ import javax.validation.constraints.NotNull; ...@@ -38,6 +38,7 @@ import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonGetter;
import org.genesys.blocks.model.AuditedVersionedModel; import org.genesys.blocks.model.AuditedVersionedModel;
import org.genesys.blocks.model.IdUUID; import org.genesys.blocks.model.IdUUID;
import org.genesys.blocks.model.JsonViews; import org.genesys.blocks.model.JsonViews;
...@@ -71,7 +72,7 @@ public abstract class AccessionData extends AuditedVersionedModel implements IdU ...@@ -71,7 +72,7 @@ public abstract class AccessionData extends AuditedVersionedModel implements IdU
@JoinColumn(name = "id") @JoinColumn(name = "id")
@JsonUnwrapped @JsonUnwrapped
@Field(type=FieldType.Auto) @Field(type=FieldType.Auto)
@QueryInit({ "geo.*", "coll.*", "pdci.*" }) @QueryInit({ "geo.*", "coll.*", "pdci.*", "lists.*" })
private AccessionId accessionId; private AccessionId accessionId;
@Column(name = "doi") @Column(name = "doi")
...@@ -531,4 +532,9 @@ public abstract class AccessionData extends AuditedVersionedModel implements IdU ...@@ -531,4 +532,9 @@ public abstract class AccessionData extends AuditedVersionedModel implements IdU
public boolean getSgsv() { public boolean getSgsv() {
return this.duplSiteStr != null && this.duplSiteStr.contains("NOR051"); return this.duplSiteStr != null && this.duplSiteStr.contains("NOR051");
} }
@JsonInclude
public Boolean getImages() {
return this.accessionId != null && this.accessionId.getImageCount() > 0;
}
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package org.genesys2.server.service; package org.genesys2.server.service;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -30,6 +31,7 @@ import org.genesys2.server.model.genesys.PDCI; ...@@ -30,6 +31,7 @@ import org.genesys2.server.model.genesys.PDCI;
import org.genesys2.server.model.impl.AccessionIdentifier3; import org.genesys2.server.model.impl.AccessionIdentifier3;
import org.genesys2.server.model.impl.Subset; import org.genesys2.server.model.impl.Subset;
import org.genesys2.server.service.filter.AccessionFilter; import org.genesys2.server.service.filter.AccessionFilter;
import org.genesys2.server.service.impl.SearchException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.genesys.blocks.auditlog.model.AuditLog; import org.genesys.blocks.auditlog.model.AuditLog;
...@@ -75,6 +77,9 @@ public interface AccessionService { ...@@ -75,6 +77,9 @@ public interface AccessionService {
*/ */
Page<Accession> list(AccessionFilter filter, Pageable page); Page<Accession> list(AccessionFilter filter, Pageable page);
Map<String, ElasticsearchService.TermResult> getSuggestions(AccessionFilter filter) throws SearchException, IOException;
/** /**
* Gets the geo bounds of maximum and minimum accession localities * Gets the geo bounds of maximum and minimum accession localities
* *
......
...@@ -33,16 +33,16 @@ import com.querydsl.core.types.Predicate; ...@@ -33,16 +33,16 @@ import com.querydsl.core.types.Predicate;
public class AccessionCollectFilter extends BasicModelFilter<AccessionCollectFilter, AccessionCollect> { public class AccessionCollectFilter extends BasicModelFilter<AccessionCollectFilter, AccessionCollect> {
/** The date. */ /** The date. */
public StringFilter date; public StringFilter collDate;
/** The numb. */ /** The numb. */
public StringFilter numb; public StringFilter collNumb;
/** The mission. */ /** The mission. */
public Set<String> mission; public Set<String> collMissId;
/** The site. */ /** The site. */
public StringFilter site; public StringFilter collSite;
/** /**
* Builds the query. * Builds the query.
...@@ -63,17 +63,17 @@ public class AccessionCollectFilter extends BasicModelFilter<AccessionCollectFil ...@@ -63,17 +63,17 @@ public class AccessionCollectFilter extends BasicModelFilter<AccessionCollectFil
final BooleanBuilder and = new BooleanBuilder(); final BooleanBuilder and = new BooleanBuilder();
super.buildPredicate(collect, collect._super, and); super.buildPredicate(collect, collect._super, and);
if (date != null) { if (collDate != null) {
and.and(date.buildQuery(collect.collDate)); and.and(collDate.buildQuery(collect.collDate));
} }
if (numb != null) { if (collNumb != null) {
and.and(numb.buildQuery(collect.collNumb)); and.and(collNumb.buildQuery(collect.collNumb));
} }
if (site != null) { if (collSite != null) {
and.and(site.buildQuery(collect.collSite)); and.and(collSite.buildQuery(collect.collSite));
} }
if (mission != null && !mission.isEmpty()) { if (collMissId != null && !collMissId.isEmpty()) {
and.and(collect.collMissId.in(mission)); and.and(collect.collMissId.in(collMissId));
} }
return and; return and;
} }
......
...@@ -61,11 +61,11 @@ public class AccessionFilter extends UuidModelFilter<AccessionFilter, Accession> ...@@ -61,11 +61,11 @@ public class AccessionFilter extends UuidModelFilter<AccessionFilter, Accession>
/** The crop name. */ /** The crop name. */
public StringFilter cropName; public StringFilter cropName;
/** The holder. */ /** The institute. */
public InstituteFilter holder; public InstituteFilter institute;
/** The acce numb. */ /** The acce numb. */
public StringFilter acceNumb; public StringFilter accessionNumber;
/** The doi. */ /** The doi. */
public Set<String> doi; public Set<String> doi;
...@@ -73,14 +73,14 @@ public class AccessionFilter extends UuidModelFilter<AccessionFilter, Accession> ...@@ -73,14 +73,14 @@ public class AccessionFilter extends UuidModelFilter<AccessionFilter, Accession>
/** The seq no. */ /** The seq no. */
public NumberFilter<Double> seqNo; public NumberFilter<Double> seqNo;
/** The taxa. */ /** The taxonomy. */
public TaxonomyFilter taxa; public TaxonomyFilter taxonomy;
/** The samp stat. */ /** The samp stat. */
public Set<Integer> sampStat; public Set<Integer> sampStat;
/** The origin. */ /** The origin. */