RED-2896: Added new message type and implementation to update assignee, workflow status and file attributes

This commit is contained in:
deiflaender 2022-01-12 15:34:08 +01:00 committed by Philipp Schramm
parent 1aee789284
commit 1a02ed425f
13 changed files with 453 additions and 66 deletions

View File

@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
public class IndexMessage {
private IndexMessageType messageType;
private String dossierId;
private String dossierTemplateId;
private String fileId;

View File

@ -0,0 +1,5 @@
package com.iqser.red.service.search.v1.model;
public enum IndexMessageType {
INSERT, UPDATE;
}

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
@Data
@Builder
@ -17,6 +18,9 @@ public class SearchRequest {
private List<String> dossierIds;
private List<String> dossierTemplateIds;
private String fileId;
private String assignee;
private String workflowStatus;
private Map<String, String> fileAttributes;
private int page;
private int pageSize;
private boolean returnSections;

View File

@ -17,9 +17,18 @@ public class SearchController implements SearchResource {
public SearchResult getDossierStatus(@RequestBody SearchRequest searchRequest) {
return searchService.search(searchRequest.getQueryString(), searchRequest.getDossierTemplateIds(),
searchRequest.getDossierIds(), searchRequest.getFileId(), searchRequest
.getPage(), searchRequest.getPageSize(), searchRequest.isReturnSections());
return searchService.search(
searchRequest.getQueryString(),
searchRequest.getDossierTemplateIds(),
searchRequest.getDossierIds(),
searchRequest.getFileId(),
searchRequest.getAssignee(),
searchRequest.getWorkflowStatus(),
searchRequest.getFileAttributes(),
searchRequest.getPage(),
searchRequest.getPageSize(),
searchRequest.isReturnSections()
);
}
}

View File

@ -19,8 +19,14 @@ public class IndexDocument implements Serializable {
private String fileId;
private String filename;
private OffsetDateTime date;
private String assignee;
private String workflowStatus;
@Builder.Default
private List<IndexSection> sections = new ArrayList<>();
@Builder.Default
private List<IndexFileAttribute> fileAttributes = new ArrayList<>();
}

View File

@ -0,0 +1,20 @@
package com.iqser.red.service.search.v1.server.model;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IndexDocumentUpdate {
private String assignee;
private String workflowStatus;
private List<IndexFileAttribute> fileAttributes;
}

View File

@ -0,0 +1,17 @@
package com.iqser.red.service.search.v1.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IndexFileAttribute {
private String name;
private String value;
}

View File

@ -3,11 +3,13 @@ package com.iqser.red.service.search.v1.server.queue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.search.v1.model.IndexMessage;
import com.iqser.red.service.search.v1.model.IndexMessageType;
import com.iqser.red.service.search.v1.server.client.FileStatusClient;
import com.iqser.red.service.search.v1.server.client.FileStatusProcessingUpdateClient;
import com.iqser.red.service.search.v1.server.model.Text;
import com.iqser.red.service.search.v1.server.service.DocumentDeleteService;
import com.iqser.red.service.search.v1.server.service.DocumentIndexService;
import com.iqser.red.service.search.v1.server.service.DocumentUpdateService;
import com.iqser.red.service.search.v1.server.service.TextStorageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -28,6 +30,7 @@ public class IndexingMessageReceiver {
private final FileStatusClient fileStatusClient;
private final FileStatusProcessingUpdateClient fileStatusProcessingUpdateClient;
private final DocumentDeleteService documentDeleteService;
private final DocumentUpdateService documentUpdateService;
@RabbitHandler
@ -38,11 +41,16 @@ public class IndexingMessageReceiver {
log.info("Processing indexing request: {}", indexRequest);
fileStatusProcessingUpdateClient.indexing(indexRequest.getDossierId(), indexRequest.getFileId());
var fileStatus = fileStatusClient.getFileStatus(indexRequest.getDossierId(), indexRequest.getFileId());
Text text = textStorageService.getText(indexRequest.getDossierId(), indexRequest.getFileId());
documentIndexService.indexDocument(indexRequest.getDossierTemplateId(), indexRequest.getDossierId(), indexRequest.getFileId(), fileStatus.getFilename(), text);
fileStatusProcessingUpdateClient.indexingSuccessful(indexRequest.getDossierId(), indexRequest.getFileId());
log.info("Successfully indexed {}", indexRequest);
if (IndexMessageType.INSERT.equals(indexRequest.getMessageType())) {
Text text = textStorageService.getText(indexRequest.getDossierId(), indexRequest.getFileId());
documentIndexService.indexDocument(indexRequest.getDossierTemplateId(), indexRequest.getDossierId(), indexRequest.getFileId(), fileStatus.getFilename(), text, fileStatus.getAssignee(), fileStatus.getWorkflowStatus(), fileStatus.getFileAttributes());
fileStatusProcessingUpdateClient.indexingSuccessful(indexRequest.getDossierId(), indexRequest.getFileId());
log.info("Successfully indexed {}", indexRequest);
} else if (IndexMessageType.UPDATE.equals(indexRequest.getMessageType())) {
documentUpdateService.updateDocument(indexRequest.getFileId(), fileStatus.getAssignee(), fileStatus.getWorkflowStatus().name(), fileStatus.getFileAttributes());
log.info("Successfully updated {}", indexRequest);
}
}

View File

@ -2,6 +2,7 @@ package com.iqser.red.service.search.v1.server.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import com.iqser.red.service.search.v1.server.client.ElasticsearchClient;
import com.iqser.red.service.search.v1.server.exception.IndexException;
import com.iqser.red.service.search.v1.server.model.*;
@ -15,6 +16,9 @@ import org.springframework.stereotype.Service;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.iqser.red.service.search.v1.server.service.IndexCreatorService.INDEX_NAME;
@ -29,11 +33,11 @@ public class DocumentIndexService {
private final ObjectMapper objectMapper;
public void indexDocument(String dossierTemplateId, String dossierId, String fileId, String filename, Text text) {
public void indexDocument(String dossierTemplateId, String dossierId, String fileId, String filename, Text text, String assignee, WorkflowStatus workflowStatus, Map<String, String> fileAttributes) {
IndexRequest indexRequest = new IndexRequest(INDEX_NAME).id(fileId);
indexRequest.setRefreshPolicy(settings.getRefreshPolicy());
indexRequest.source(toJson(convert(dossierTemplateId, dossierId, fileId, filename, text)), XContentType.JSON);
indexRequest.source(toJson(convert(dossierTemplateId, dossierId, fileId, filename, text, assignee, workflowStatus, fileAttributes)), XContentType.JSON);
try {
client.index(indexRequest, RequestOptions.DEFAULT);
@ -53,7 +57,7 @@ public class DocumentIndexService {
}
private IndexDocument convert(String dossierTemplateId, String dossierId, String fileId, String filename, Text text) {
private IndexDocument convert(String dossierTemplateId, String dossierId, String fileId, String filename, Text text, String assignee, WorkflowStatus workflowStatus, Map<String, String> fileAttributes) {
return IndexDocument.builder()
.dossierTemplateId(dossierTemplateId)
@ -62,9 +66,19 @@ public class DocumentIndexService {
.filename(filename)
.sections(text.getSectionTexts().stream().map(this::convert).collect(Collectors.toList()))
.date(OffsetDateTime.now())
.fileAttributes(convertFileAttributes(fileAttributes))
.assignee(assignee)
.workflowStatus(workflowStatus.name())
.build();
}
private List<IndexFileAttribute> convertFileAttributes(Map<String, String> fileAttributes){
List<IndexFileAttribute> converted = new ArrayList<>();
fileAttributes.entrySet().forEach(entry -> converted.add(new IndexFileAttribute(entry.getKey(), entry.getValue())));
return converted;
}
private IndexSection convert(SectionText sectionText) {

View File

@ -0,0 +1,53 @@
package com.iqser.red.service.search.v1.server.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.search.v1.server.client.ElasticsearchClient;
import com.iqser.red.service.search.v1.server.model.IndexDocumentUpdate;
import com.iqser.red.service.search.v1.server.model.IndexFileAttribute;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.iqser.red.service.search.v1.server.service.IndexCreatorService.INDEX_NAME;
@Service
@RequiredArgsConstructor
public class DocumentUpdateService {
private final ObjectMapper objectMapper;
private final ElasticsearchClient client;
@SneakyThrows
public void updateDocument(String fileId, String assignee, String workflowStatus, Map<String, String> fileAttributes) {
var indexUpdateRequest = IndexDocumentUpdate.builder().assignee(assignee).workflowStatus(workflowStatus).fileAttributes(convertFileAttributes(fileAttributes)).build();
UpdateRequest request = new UpdateRequest(INDEX_NAME, fileId);
request.doc(objectMapper.writeValueAsString(indexUpdateRequest), XContentType.JSON);
UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
if (updateResponse.status().getStatus() < 200 || updateResponse.status().getStatus() > 204) {
throw new IllegalStateException("Document could not be updated. HTTP error " + updateResponse.status().getStatus());
}
}
private List<IndexFileAttribute> convertFileAttributes(Map<String, String> fileAttributes) {
List<IndexFileAttribute> converted = new ArrayList<>();
if (fileAttributes != null && !fileAttributes.isEmpty()) {
fileAttributes.forEach((key, value) -> converted.add(new IndexFileAttribute(key, value)));
}
return converted;
}
}

View File

@ -7,6 +7,7 @@ import com.iqser.red.service.search.v1.server.client.ElasticsearchClient;
import com.iqser.red.service.search.v1.server.exception.IndexException;
import com.iqser.red.service.search.v1.server.model.Query;
import com.iqser.red.service.search.v1.server.utils.QueryStringConverter;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
@ -38,16 +39,26 @@ public class SearchService {
private final ElasticsearchClient client;
public SearchResult search(String queryString, List<String> dossierTemplateIds, List<String> dossierIds, String fileId, int page, int pageSize,
boolean returnSections) {
public SearchResult search(
String queryString,
List<String> dossierTemplateIds,
List<String> dossierIds,
String fileId,
String assignee,
String workflowStatus,
Map<String, String> fileAttributes,
int page,
int pageSize,
boolean returnSections
) {
Query query = QueryStringConverter.convert(queryString);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(convertQuery(query, dossierTemplateIds, dossierIds, fileId, returnSections))
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(convertQuery(query, dossierTemplateIds, dossierIds, fileId, assignee, workflowStatus, fileAttributes, returnSections))
.from(page * pageSize)
.size(pageSize)
.fetchSource(new String[]{"dossierId", "fileId"}, new String[]{"sections"})
.highlighter(new HighlightBuilder().field("sections.text").field("filename").highlighterType("fvh"))
.highlighter(new HighlightBuilder().field("sections.text").field("filename").field("fileAttributes.value").highlighterType("fvh"))//
.trackScores(true);
SearchRequest request = new SearchRequest(INDEX_NAME).source(searchSourceBuilder);
@ -68,38 +79,38 @@ public class SearchService {
}
private QueryBuilder convertQuery(Query query, List<String> dossierTemplateIds, List<String> dossierIds, String fileId, boolean returnSections) {
private QueryBuilder convertQuery(Query query, List<String> dossierTemplateIds, List<String> dossierIds, String fileId, String assignee, String workflowStatus, Map<String, String> fileAttributes, boolean returnSections) {
BoolQueryBuilder entireQuery = QueryBuilders.boolQuery();
BoolQueryBuilder sectionsQueries = QueryBuilders.boolQuery();
for (String must : query.getMusts()) {
QueryBuilder textPhraseQuery = QueryBuilders.matchPhraseQuery("sections.text", must.toLowerCase(Locale.ROOT))
.queryName(must);
QueryBuilder filenamePhraseQuery = QueryBuilders.matchPhraseQuery("filename", must.toLowerCase(Locale.ROOT))
.queryName("filename." + must);
QueryBuilder textPhraseQuery = QueryBuilders.matchPhraseQuery("sections.text", must.toLowerCase(Locale.ROOT)).queryName(must);
QueryBuilder filenamePhraseQuery = QueryBuilders.matchPhraseQuery("filename", must.toLowerCase(Locale.ROOT)).queryName("filename." + must);
QueryBuilder fileAttributesPhraseQuery = QueryBuilders.matchPhraseQuery("fileAttributes.value", must.toLowerCase(Locale.ROOT)).queryName("fileAttributes." + must);
QueryBuilder filenameOrTextMustQuery = QueryBuilders.boolQuery()
.should(textPhraseQuery)
.should(filenamePhraseQuery);
.should(filenamePhraseQuery)
.should(fileAttributesPhraseQuery);
entireQuery.must(filenameOrTextMustQuery);
sectionsQueries.should(textPhraseQuery);
}
for (String should : query.getShoulds()) {
QueryBuilder textTermQuery = QueryBuilders.matchPhraseQuery("sections.text", should.toLowerCase(Locale.ROOT))
.queryName(should);
QueryBuilder filenameTermQuery = QueryBuilders.matchPhraseQuery("filename", should.toLowerCase(Locale.ROOT))
.queryName("filename." + should);
QueryBuilder textTermQuery = QueryBuilders.matchPhraseQuery("sections.text", should.toLowerCase(Locale.ROOT)).queryName(should);
QueryBuilder filenameTermQuery = QueryBuilders.matchPhraseQuery("filename", should.toLowerCase(Locale.ROOT)).queryName("filename." + should);
QueryBuilder fileAttributesPhraseQuery = QueryBuilders.matchPhraseQuery("fileAttributes.value", should.toLowerCase(Locale.ROOT)).queryName("fileAttributes." + should);
entireQuery.should(textTermQuery);
entireQuery.should(filenameTermQuery);
entireQuery.should(fileAttributesPhraseQuery);
sectionsQueries.should(textTermQuery);
}
if (returnSections) {
NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("sections", sectionsQueries, ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setSize(100)
.setFetchSourceContext(new FetchSourceContext(true, new String[]{"sections.headline", "sections.sectionNumber", "sections.pages"}, new String[]{"sections.text"})));
.innerHit(new InnerHitBuilder().setSize(100).setFetchSourceContext(new FetchSourceContext(true, new String[]{"sections.headline", "sections.sectionNumber", "sections.pages"}, new String[]{"sections.text"})));
entireQuery.should(nestedQuery);
}
@ -129,10 +140,31 @@ public class SearchService {
}
if (fileId != null) {
if (StringUtils.isNotEmpty(fileId)) {
filterQuery.must(QueryBuilders.matchQuery("fileId", fileId));
}
if (StringUtils.isNotEmpty(assignee)) {
filterQuery.must(QueryBuilders.matchQuery("assignee", assignee));
}
if (StringUtils.isNotEmpty(workflowStatus)) {
filterQuery.must(QueryBuilders.matchQuery("workflowStatus", workflowStatus));
}
if (fileAttributes != null && !fileAttributes.isEmpty()) {
var fileAttributesQueryBuilder = QueryBuilders.boolQuery();
for (var fileAttributeKey : fileAttributes.keySet()) {
fileAttributesQueryBuilder.filter(QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("fileAttributes.name", fileAttributeKey))
.must(QueryBuilders.matchQuery("fileAttributes.value", fileAttributes.get(fileAttributeKey))));
}
filterQuery.must(fileAttributesQueryBuilder);
}
return QueryBuilders.boolQuery().filter(filterQuery).must(entireQuery);
}
@ -151,7 +183,11 @@ public class SearchService {
private MatchedDocument convertSearchHit(SearchHit hit, Query query) {
Set<String> matchesTerms = Arrays.stream(hit.getMatchedQueries()).map(match -> match.contains("filename.") ? match.replace("filename.", "") : match).collect(Collectors.toSet());
Set<String> matchesTerms = Arrays.stream(hit.getMatchedQueries())
.map(match -> match.contains("filename.") ? match.replace("filename.", "") : match)
.map(match -> match.contains("fileAttributes.") ? match.replace("fileAttributes.", "") : match)
.collect(Collectors.toSet());
Set<String> unmatchedTerms = Stream.concat(query.getMusts().stream(), query.getShoulds().stream())
.filter(term -> !matchesTerms.contains(term))
.collect(Collectors.toSet());

View File

@ -16,6 +16,25 @@
"indexTime": {
"type": "date"
},
"assignee": {
"type": "keyword"
},
"workflowStatus": {
"type": "keyword"
},
"fileAttributes" : {
"type": "nested",
"include_in_parent": true,
"properties": {
"name": {
"type": "keyword"
},
"value": {
"type": "text",
"term_vector": "with_positions_offsets"
}
}
},
"sections": {
"type": "nested",
"include_in_parent": true,

View File

@ -1,10 +1,13 @@
package com.iqser.red.service.search.v1.server.service;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.util.Arrays;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import com.iqser.red.service.search.v1.model.MatchedDocument;
import com.iqser.red.service.search.v1.model.SearchResult;
import com.iqser.red.service.search.v1.server.client.FileStatusClient;
import com.iqser.red.service.search.v1.server.client.FileStatusProcessingUpdateClient;
import com.iqser.red.service.search.v1.server.model.Text;
import lombok.SneakyThrows;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -14,11 +17,11 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.shaded.org.apache.commons.lang.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.search.v1.model.SearchResult;
import com.iqser.red.service.search.v1.server.client.FileStatusClient;
import com.iqser.red.service.search.v1.server.client.FileStatusProcessingUpdateClient;
import com.iqser.red.service.search.v1.server.model.Text;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {AbstractElasticsearchIntegrationTest.WAIT_FOR_WRITE_REQUESTS})
@ -36,16 +39,208 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
@Autowired
private DocumentDeleteService documentDeleteService;
@Autowired
private DocumentUpdateService documentUpdateService;
@MockBean
private FileStatusClient fileStatusClient;
@MockBean
private FileStatusProcessingUpdateClient fileStatusProcessingUpdateClient;
private final long UPDATE_TIMER = 1500;
@Test
@SneakyThrows
public void testSearchFileAttribute() {
// Arrange
ClassPathResource textResource = new ClassPathResource("files/Text2.json");
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-1.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-2.pdf", text, "UserId2", WorkflowStatus.NEW, Map.of("F2Key", "F2Value"));
// Act & Assert 1
SearchResult result = searchService.search("F1Value", null, null, null, null, null, null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
}
/*
* Index two documents and delete one
* Index two documents and filter
*/
@Test
@SneakyThrows
public void testFilter() {
// Arrange
ClassPathResource textResource = new ClassPathResource("files/Text2.json");
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-1.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-2.pdf", text, "UserId2", WorkflowStatus.NEW, Map.of("F2Key", "F2Value"));
// Act & Assert 1
SearchResult result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.APPROVED.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 2
result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.NEW.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(2);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 3
documentUpdateService.updateDocument("fileId1", "UserId2", WorkflowStatus.APPROVED.name(), Map.of("F2Key", "F2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, "UserId2", WorkflowStatus.NEW.name(), Map.of("F2Key", "F2Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 4
documentUpdateService.updateDocument("fileId2", "UserId2", WorkflowStatus.APPROVED.name(), Map.of("F2Key", "F2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, "UserId2", WorkflowStatus.APPROVED.name(), Map.of("F2Key", "F2Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(2);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
}
/*
* Index two documents, update one and filter by assignee
*/
@Test
@SneakyThrows
public void testFilterByAssignee() {
// Arrange
ClassPathResource textResource = new ClassPathResource("files/Text2.json");
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-1.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-2.pdf", text, "UserId2", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act & Assert 1
SearchResult result = searchService.search("S-Metolachlor", null, null, null, "UserId2", null, null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 2
documentUpdateService.updateDocument("fileId1", "UserId2", WorkflowStatus.APPROVED.name(), Map.of("U2Key", "U2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, "UserId2", null, null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(2);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
}
/*
* Index two documents, update one and filter by assignee
*/
@Test
@SneakyThrows
public void testFilterByWorkflowStatus() {
// Arrange
ClassPathResource textResource = new ClassPathResource("files/Text2.json");
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-1.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-2.pdf", text, "UserId2", WorkflowStatus.NEW, Map.of("F2Key", "F2Value"));
// Act & Assert 1
SearchResult result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.APPROVED.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 2
result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.NEW.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(2);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 3
documentUpdateService.updateDocument("fileId1", "UserId2", WorkflowStatus.APPROVED.name(), Map.of("U2Key", "U2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.APPROVED.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
// Act & Assert 4
result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.NEW.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 5
documentUpdateService.updateDocument("fileId2", "UserId2", WorkflowStatus.APPROVED.name(), Map.of("U2Key", "U2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, null, WorkflowStatus.APPROVED.name(), null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(2);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
}
/*
* Index two documents, update one and filter by file attributes
*/
@Test
@SneakyThrows
public void testFilterByFileAttributes() {
// Arrange
ClassPathResource textResource = new ClassPathResource("files/Text2.json");
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-1.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06-2.pdf", text, "UserId2", WorkflowStatus.NEW, Map.of("F2Key", "F2Value"));
// Act & Assert 1
SearchResult result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
// Act & Assert 2
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F2Key", "F2Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId2");
// Act & Assert 3
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F2Key", "does-not-exist"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 4
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("Key-does-not-exist", "F1Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 5
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1Value", "F2Key", "F2Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 6
documentUpdateService.updateDocument("fileId1", "UserId", WorkflowStatus.NEW.name(), Map.of("F1Key", "F1ValueNEW"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 7
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1ValueNEW"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
// Act & Assert 8
documentUpdateService.updateDocument("fileId1", "UserId", WorkflowStatus.NEW.name(), Map.of("F1Key", "F1Value", "F2Key", "F2Value"));
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1Value", "F2Key", "F2Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
assertThat(result.getMatchedDocuments().stream().map(MatchedDocument::getFileId)).contains("fileId1");
// Act & Assert 9
documentUpdateService.updateDocument("fileId1", "UserId", WorkflowStatus.NEW.name(), null);
Thread.sleep(UPDATE_TIMER);
result = searchService.search("S-Metolachlor", null, null, null, null, null, Map.of("F1Key", "F1Value"), 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
}
@Test
public void testTwoDocumentsAndDeleteOne() throws IOException {
// Arrange
@ -55,11 +250,11 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
ClassPathResource textResource2 = new ClassPathResource("files/Text2.json");
Text text2 = objectMapper.readValue(textResource2.getInputStream(), Text.class);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "Single Study - Oral (Gavage) Mouse.pdf", text);
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06.pdf", text2);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", "Single Study - Oral (Gavage) Mouse.pdf", text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
documentIndexService.indexDocument("template2", "dossierId2", "fileId2", "S-Metolachlor_RAR_01_Volume_1_2018-09-06.pdf", text2, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act & Assert 1
SearchResult result = searchService.search("S-Metolachlor", null, Arrays.asList("dossierId1", "dossierId2"), null, 0, 10, false);
SearchResult result = searchService.search("S-Metolachlor", null, Arrays.asList("dossierId1", "dossierId2"), null, null, null, null, 0, 10, false);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -67,17 +262,17 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
documentDeleteService.deleteDocument("fileId1");
// Act & Assert 2
result = searchService.search("hans klaus single", null, Arrays.asList("dossierId1", "dossierId2"), null, 0, 10, true);
result = searchService.search("hans klaus single", null, Arrays.asList("dossierId1", "dossierId2"), null, null, null, null, 0, 10, true);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
// Act & Assert 3
result = searchService.search("hans klaus single", null, Arrays.asList("dossierId3", "dossierId4"), null, 0, 10, true);
result = searchService.search("hans klaus single", null, Arrays.asList("dossierId3", "dossierId4"), null, null, null, null, 0, 10, true);
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
// Act & Assert 4
result = searchService.search("hans klaus single", Arrays.asList("template1", "template2"), null, null, 0, 10, true);
result = searchService.search("hans klaus single", Arrays.asList("template1", "template2"), null, null, null, null, null, 0, 10, true);
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -94,10 +289,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-skywalker-42.pdf";
String searchString = "szedhsegkekhglghserlkghrsdvkerxyfdbvkrdjgh";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 1, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 1, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(0);
@ -114,10 +309,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-skywalker-42.pdf";
String searchString = fileName;
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -136,10 +331,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-blankwalker 42.pdf";
String searchString = fileName;
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -159,10 +354,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-skywalker-42.pdf";
String searchString = "luke";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -181,10 +376,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-skywalker-42.pdf";
String searchString = "luke-skywalker-42";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -204,10 +399,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
String fileName = "luke-skywalker-42.pdf";
String matchedString = fileName;
String searchString = "\"" + matchedString + "\"";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -227,10 +422,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
String fileName = "luke-skywalker-42.pdf";
String matchedString = "luke";
String searchString = "\"" + matchedString + "\"";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -250,10 +445,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
String fileName = "luke-skywalker-42.pdf";
String matchedString = "luke-skywalker-42";
String searchString = "\"luke-skywalker-42\"";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -273,10 +468,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
String fileName = "luke-blankwalker 42.pdf";
String matchedString = fileName;
String searchString = "\"" + matchedString + "\"";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);
@ -295,10 +490,10 @@ public class IndexCreatorTest extends AbstractElasticsearchIntegrationTest {
Text text = objectMapper.readValue(textResource.getInputStream(), Text.class);
String fileName = "luke-skywalker-42.pdf";
String searchString = "14C]-SDS-46851";
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text);
documentIndexService.indexDocument("template1", "dossierId1", "fileId1", fileName, text, "UserId", WorkflowStatus.NEW, Map.of("F1Key", "F1Value"));
// Act
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, 0, 10, true);
SearchResult result = searchService.search(searchString, null, Arrays.asList("dossierId1"), null, null, null, null, 0, 10, true);
// Assert
assertThat(result.getMatchedDocuments().size()).isEqualTo(1);