feat(search): extend NlQueryInterpretation with resolvedTags + tagsApplied
Positional record fields added; all 3 construction sites updated with neutral defaults; NlQueryParserService wired for TagService (4th constructor arg); NlQueryParserServiceTest and NlSearchControllerTest synced. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,8 +15,12 @@ public record NlQueryInterpretation(
|
|||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
List<String> keywords,
|
List<String> keywords,
|
||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
List<TagHint> resolvedTags,
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
String rawQuery,
|
String rawQuery,
|
||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
boolean keywordsApplied
|
boolean keywordsApplied,
|
||||||
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
boolean tagsApplied
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,15 @@ import org.raddatz.familienarchiv.exception.DomainException;
|
|||||||
import org.raddatz.familienarchiv.exception.ErrorCode;
|
import org.raddatz.familienarchiv.exception.ErrorCode;
|
||||||
import org.raddatz.familienarchiv.person.Person;
|
import org.raddatz.familienarchiv.person.Person;
|
||||||
import org.raddatz.familienarchiv.person.PersonService;
|
import org.raddatz.familienarchiv.person.PersonService;
|
||||||
|
import org.raddatz.familienarchiv.tag.Tag;
|
||||||
import org.raddatz.familienarchiv.tag.TagOperator;
|
import org.raddatz.familienarchiv.tag.TagOperator;
|
||||||
|
import org.raddatz.familienarchiv.tag.TagService;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -28,10 +31,13 @@ public class NlQueryParserService {
|
|||||||
private static final int MAX_QUERY = 500;
|
private static final int MAX_QUERY = 500;
|
||||||
private static final int MAX_NAME_LENGTH = 200;
|
private static final int MAX_NAME_LENGTH = 200;
|
||||||
private static final int MAX_CANDIDATES = 10;
|
private static final int MAX_CANDIDATES = 10;
|
||||||
|
private static final int MIN_TAG_TERM = 3;
|
||||||
|
private static final int MAX_RESOLVED_TAGS = 10;
|
||||||
|
|
||||||
private final OllamaClient ollamaClient;
|
private final OllamaClient ollamaClient;
|
||||||
private final PersonService personService;
|
private final PersonService personService;
|
||||||
private final DocumentService documentService;
|
private final DocumentService documentService;
|
||||||
|
private final TagService tagService;
|
||||||
|
|
||||||
public NlSearchResponse search(String query, Pageable pageable) {
|
public NlSearchResponse search(String query, Pageable pageable) {
|
||||||
if (query == null || query.length() < MIN_QUERY || query.length() > MAX_QUERY) {
|
if (query == null || query.length() < MIN_QUERY || query.length() > MAX_QUERY) {
|
||||||
@@ -50,7 +56,7 @@ public class NlQueryParserService {
|
|||||||
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
||||||
List.of(), resolution.ambiguous(),
|
List.of(), resolution.ambiguous(),
|
||||||
ext.dateFrom(), ext.dateTo(),
|
ext.dateFrom(), ext.dateTo(),
|
||||||
keywords, ext.rawQuery(), false);
|
keywords, List.of(), ext.rawQuery(), false, false);
|
||||||
return new NlSearchResponse(DocumentSearchResult.of(List.of()), interpretation);
|
return new NlSearchResponse(DocumentSearchResult.of(List.of()), interpretation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +71,7 @@ public class NlQueryParserService {
|
|||||||
DocumentSearchResult docs = documentService.searchDocumentsByPersonId(
|
DocumentSearchResult docs = documentService.searchDocumentsByPersonId(
|
||||||
personId, ext.dateFrom(), ext.dateTo(), pageable);
|
personId, ext.dateFrom(), ext.dateTo(), pageable);
|
||||||
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
||||||
resolved, List.of(), ext.dateFrom(), ext.dateTo(), keywords, ext.rawQuery(), false);
|
resolved, List.of(), ext.dateFrom(), ext.dateTo(), keywords, List.of(), ext.rawQuery(), false, false);
|
||||||
return new NlSearchResponse(docs, interpretation);
|
return new NlSearchResponse(docs, interpretation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +88,7 @@ public class NlQueryParserService {
|
|||||||
DocumentSearchResult docs = documentService.searchDocuments(filters, DocumentSort.DATE, "desc", pageable);
|
DocumentSearchResult docs = documentService.searchDocuments(filters, DocumentSort.DATE, "desc", pageable);
|
||||||
boolean keywordsApplied = !text.isBlank();
|
boolean keywordsApplied = !text.isBlank();
|
||||||
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
NlQueryInterpretation interpretation = new NlQueryInterpretation(
|
||||||
resolved, List.of(), ext.dateFrom(), ext.dateTo(), keywords, ext.rawQuery(), keywordsApplied);
|
resolved, List.of(), ext.dateFrom(), ext.dateTo(), keywords, List.of(), ext.rawQuery(), keywordsApplied, false);
|
||||||
return new NlSearchResponse(docs, interpretation);
|
return new NlSearchResponse(docs, interpretation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import org.raddatz.familienarchiv.exception.DomainException;
|
|||||||
import org.raddatz.familienarchiv.exception.ErrorCode;
|
import org.raddatz.familienarchiv.exception.ErrorCode;
|
||||||
import org.raddatz.familienarchiv.person.Person;
|
import org.raddatz.familienarchiv.person.Person;
|
||||||
import org.raddatz.familienarchiv.person.PersonService;
|
import org.raddatz.familienarchiv.person.PersonService;
|
||||||
|
import org.raddatz.familienarchiv.tag.Tag;
|
||||||
import org.raddatz.familienarchiv.tag.TagOperator;
|
import org.raddatz.familienarchiv.tag.TagOperator;
|
||||||
|
import org.raddatz.familienarchiv.tag.TagService;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ class NlQueryParserServiceTest {
|
|||||||
@Mock OllamaClient ollamaClient;
|
@Mock OllamaClient ollamaClient;
|
||||||
@Mock PersonService personService;
|
@Mock PersonService personService;
|
||||||
@Mock DocumentService documentService;
|
@Mock DocumentService documentService;
|
||||||
|
@Mock TagService tagService;
|
||||||
|
|
||||||
NlQueryParserService service;
|
NlQueryParserService service;
|
||||||
|
|
||||||
@@ -40,11 +43,12 @@ class NlQueryParserServiceTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
MockitoAnnotations.openMocks(this);
|
MockitoAnnotations.openMocks(this);
|
||||||
service = new NlQueryParserService(ollamaClient, personService, documentService);
|
service = new NlQueryParserService(ollamaClient, personService, documentService, tagService);
|
||||||
when(documentService.searchDocuments(any(), any(), any(), any()))
|
when(documentService.searchDocuments(any(), any(), any(), any()))
|
||||||
.thenReturn(DocumentSearchResult.of(List.of()));
|
.thenReturn(DocumentSearchResult.of(List.of()));
|
||||||
when(documentService.searchDocumentsByPersonId(any(), any(), any(), any()))
|
when(documentService.searchDocumentsByPersonId(any(), any(), any(), any()))
|
||||||
.thenReturn(DocumentSearchResult.of(List.of()));
|
.thenReturn(DocumentSearchResult.of(List.of()));
|
||||||
|
when(tagService.findByNameContaining(anyString())).thenReturn(List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Factory helpers ---
|
// --- Factory helpers ---
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class NlSearchControllerTest {
|
|||||||
PersonHint hint = new PersonHint(UUID.randomUUID(), "Walter Raddatz");
|
PersonHint hint = new PersonHint(UUID.randomUUID(), "Walter Raddatz");
|
||||||
NlQueryInterpretation interp = new NlQueryInterpretation(
|
NlQueryInterpretation interp = new NlQueryInterpretation(
|
||||||
List.of(hint), List.of(), null, null,
|
List.of(hint), List.of(), null, null,
|
||||||
List.of("Krieg"), "Briefe von Walter im Krieg", true);
|
List.of("Krieg"), List.of(), "Briefe von Walter im Krieg", true, false);
|
||||||
return new NlSearchResponse(DocumentSearchResult.of(List.of()), interp);
|
return new NlSearchResponse(DocumentSearchResult.of(List.of()), interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ class NlSearchControllerTest {
|
|||||||
PersonHint b = new PersonHint(UUID.randomUUID(), "Walter Schmidt");
|
PersonHint b = new PersonHint(UUID.randomUUID(), "Walter Schmidt");
|
||||||
NlQueryInterpretation interp = new NlQueryInterpretation(
|
NlQueryInterpretation interp = new NlQueryInterpretation(
|
||||||
List.of(), List.of(a, b), null, null,
|
List.of(), List.of(a, b), null, null,
|
||||||
List.of(), "Briefe von Walter", false);
|
List.of(), List.of(), "Briefe von Walter", false, false);
|
||||||
NlSearchResponse resp = new NlSearchResponse(DocumentSearchResult.of(List.of()), interp);
|
NlSearchResponse resp = new NlSearchResponse(DocumentSearchResult.of(List.of()), interp);
|
||||||
when(nlQueryParserService.search(anyString(), any())).thenReturn(resp);
|
when(nlQueryParserService.search(anyString(), any())).thenReturn(resp);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user