diff --git a/Changes b/Changes
index 7df990f0..00165a71 100644
--- a/Changes
+++ b/Changes
@@ -12,6 +12,8 @@
- Added category to Piwik calls. (diewald)
- Add SpaCy with STTS to annotation assistant. (diewald)
- Support field objects in search responses. (diewald)
+ - Add fields to search API (necessary
+ for future Kustvakt releases). (diewald)
0.54 2024-06-10
- Remove deprecated 'matchInfo' API path. (diewald, margaretha)
diff --git a/lib/Kalamar/Controller/Search.pm b/lib/Kalamar/Controller/Search.pm
index 5edd2ae5..47d2b1e7 100644
--- a/lib/Kalamar/Controller/Search.pm
+++ b/lib/Kalamar/Controller/Search.pm
@@ -6,6 +6,8 @@ use Mojo::Util qw/quote/;
use Mojo::JSON;
use POSIX 'ceil';
+our @search_fields = qw!ID UID textSigle layerInfo title subTitle pubDate author availability snippet!;
+
# TODO:
# Support server timing API
#
@@ -20,6 +22,9 @@ use POSIX 'ceil';
#
# TODO:
# set caches with timing like '120min'
+#
+# TODO:
+# Use nested fields
# Query endpoint
sub query {
@@ -121,6 +126,10 @@ sub query {
# From Mojolicious::Plugin::Search::Index
$query{offset} = $v->param('o') || ((($page // 1) - 1) * ($items_per_page || 1));
+
+ # Add requested fields
+ $query{fields} = join ',', @search_fields;
+
# Create remote request URL
my $url = Mojo::URL->new($c->korap->api);
$url->path('search');
diff --git a/t/fixtures.t b/t/fixtures.t
index 76cefa6c..c3fbfdc0 100644
--- a/t/fixtures.t
+++ b/t/fixtures.t
@@ -45,6 +45,16 @@ $err = $t->get_ok('/v1.0/search?q=baum&ql=poliqarp&offset=0&count=25')
;
is(defined $err ? $err->text : '', '');
+$err = $t->get_ok('/v1.0/search?q=baum&ql=poliqarp&offset=0&count=25&fields=textSigle')
+ ->status_is(200)
+ ->json_is('/meta/count', 25)
+ ->json_is('/meta/serialQuery', "tokens:s:Baum")
+ ->json_hasnt('/matches/0/docSigle')
+ ->json_is('/matches/0/textSigle', "GOE/AGI/00000")
+ ->tx->res->dom->at('#error')
+ ;
+is(defined $err ? $err->text : '', '');
+
$t->get_ok('/v1.0/corpus/WPD15/232/39681/p2133-2134?spans=false&foundry=*')
->status_is(200)
diff --git a/t/fixtures/response_query_baum_o0_c25_ftextsigle.json b/t/fixtures/response_query_baum_o0_c25_ftextsigle.json
new file mode 100644
index 00000000..802a637d
--- /dev/null
+++ b/t/fixtures/response_query_baum_o0_c25_ftextsigle.json
@@ -0,0 +1,58 @@
+{
+ "status" : 200,
+ "json" : {
+ "@context" : "http://korap.ids-mannheim.de/ns/KoralQuery/v0.3/context.jsonld",
+ "meta" : {
+ "count" : 25,
+ "startIndex" : 0,
+ "authorized" : null,
+ "timeout" : 120000,
+ "context" : {
+ "left" : ["token",40],
+ "right" : ["token",40]
+ },
+ "fields" : ["textSigle"],
+ "version" : "0.55.7",
+ "benchmark" : "0.120577834 s",
+ "totalResults" : 51,
+ "serialQuery" : "tokens:s:Baum",
+ "itemsPerPage" : 25
+ },
+ "query" : {
+ "@type" : "koral:token",
+ "wrap" : {
+ "@type" : "koral:term",
+ "layer" : "orth",
+ "key" : "Baum",
+ "match" : "match:eq",
+ "foundry" : "opennlp",
+ "rewrites" : [
+ {
+ "@type" : "koral:rewrite",
+ "src" : "Kustvakt",
+ "operation" : "operation:injection",
+ "scope" : "foundry"
+ }
+ ]
+ }
+ },
+ "matches" : [
+ {
+ "field" : "tokens",
+ "textSigle" : "GOE/AGI/00000",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "sie etwas bedeuten zu wollen und machte mit der Oberlippe eine fatale Miene. ich sprach sehr viel mit ihr durch, sie war überall zu Hause und merkte gut auf die Gegenstände. so fragte sie mich einmal, was das für ein Baum sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen Baum unterscheiden könne",
+ "matchID" : "match-GOE/AGI/00000-p2030-2031"
+ },
+ {
+ "field" : "tokens",
+ "textSigle" : "GOE/AGI/00001",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "für ein Baum sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen Baum unterscheiden könne. sie gehe, sagte sie, nach Bozen auf die Messe, wo ich doch wahrscheinlich auch hinzöge. wenn sie mich dort anträfe, müsse ich ihr einen Jahrmarkt kaufen, welches ich ihr denn auch versprach. dort wollte sie auch ihre neue",
+ "matchID" : "match-GOE/AGI/00000-p2068-2069"
+ }
+ ]
+ }
+}
diff --git a/t/server/mock.pl b/t/server/mock.pl
index 88ec0237..e9e91d4e 100644
--- a/t/server/mock.pl
+++ b/t/server/mock.pl
@@ -7,6 +7,9 @@
use warnings;
use Mojo::File qw/path/;
use Mojo::Util qw/slugify/;
+use Kalamar::Controller::Search;
+
+our @default_search_fields = @Kalamar::Controller::Search::search_fields;
# This is an API fake server with fixtures
@@ -139,6 +142,7 @@
$v->optional('context');
$v->optional('offset');
$v->optional('pipes');
+ $v->optional('fields');
$v->optional('cutoff')->in(qw/true false/);
$c->app->log->debug('Receive request');
@@ -171,6 +175,10 @@
push @slug_base, 'cq' if defined $v->param('cq');
push @slug_base, 'p' . $v->param('pipes') if defined $v->param('pipes');
+ if (defined $v->param('fields') && ($v->param('fields') ne join(',', @default_search_fields))) {
+ push @slug_base, 'f' .join('-', split(',', $v->param('fields')));
+ };
+
# Get response based on query parameter
my $response = $c->load_response('query_' . slugify(join('_', @slug_base)));