package gov.nysenate.openleg.dao.law.search; import gov.nysenate.openleg.client.view.law.LawDocView; import gov.nysenate.openleg.dao.base.ElasticBaseDao; import gov.nysenate.openleg.dao.base.LimitOffset; import gov.nysenate.openleg.dao.base.SearchIndex; import gov.nysenate.openleg.model.law.LawDocId; import gov.nysenate.openleg.model.law.LawDocument; import gov.nysenate.openleg.model.search.SearchResults; import gov.nysenate.openleg.util.OutputUtils; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.highlight.HighlightBuilder; import org.elasticsearch.search.rescore.RescoreBuilder; import org.elasticsearch.search.sort.SortBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import java.time.LocalDate; import java.util.Arrays; import java.util.Collection; import java.util.List; /** {@inheritDoc} */ @Repository public class ElasticLawSearchDao extends ElasticBaseDao implements LawSearchDao { private static final Logger logger = LoggerFactory.getLogger(ElasticLawSearchDao.class); protected static String lawIndexName = SearchIndex.LAW.getIndexName(); protected static List<HighlightBuilder.Field> highlightFields = Arrays.asList(new HighlightBuilder.Field("text").numOfFragments(5), new HighlightBuilder.Field("title").numOfFragments(0)); /** {@inheritDoc} */ @Override public SearchResults<LawDocId> searchLawDocs(QueryBuilder query, QueryBuilder postFilter, RescoreBuilder.Rescorer rescorer, List<SortBuilder> sort, LimitOffset limOff) { SearchRequestBuilder searchBuilder = getSearchRequest(lawIndexName, query, postFilter, highlightFields, rescorer, sort, limOff, true); SearchResponse response = searchBuilder.execute().actionGet(); return getSearchResults(response, limOff, this::getLawDocIdFromHit); } /** {@inheritDoc} */ @Override public void updateLawIndex(LawDocument lawDoc) { if (lawDoc != null) { updateLawIndex(Arrays.asList(lawDoc)); } } /** {@inheritDoc} */ @Override public void updateLawIndex(Collection<LawDocument> lawDocs) { if (lawDocs != null && !lawDocs.isEmpty()) { BulkRequestBuilder bulkRequest = searchClient.prepareBulk(); lawDocs.stream().map(doc -> new LawDocView(doc)).forEach(docView -> { bulkRequest.add( searchClient.prepareIndex(lawIndexName, docView.getLawId(), createSearchId(docView)) .setSource(OutputUtils.toJson(docView))); }); safeBulkRequestExecute(bulkRequest); } } /** {@inheritDoc} */ @Override public void deleteLawDocFromIndex(LawDocId lawDocId) { if (lawDocId != null) { deleteEntry(lawIndexName, lawDocId.getLawId(), createSearchId(lawDocId)); } } /** {@inheritDoc} */ @Override protected List<String> getIndices() { return Arrays.asList(lawIndexName); } /** --- Internal --- */ private LawDocId getLawDocIdFromHit(SearchHit hit) { String locationId = hit.getId(); String docId = hit.getType() + locationId; return new LawDocId(docId, LocalDate.parse((String) hit.getSource().get("activeDate"))); } private String createSearchId(LawDocId lawDocId) { return lawDocId.getLocationId(); } private String createSearchId(LawDocView lawDocView) { return lawDocView.getLocationId(); } }