#2731 add SearchApiManager

This commit is contained in:
Shinsuke Sugaya 2023-03-28 22:54:53 +09:00
parent a8c9ed3f41
commit f0cfcaf149
8 changed files with 1489 additions and 287 deletions

View file

@ -6,12 +6,12 @@ info:
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.11
version: 14.8.0
externalDocs:
description: API Documentation for Fess
url: https://fess.codelibs.org/14.8/api/
servers:
- url: http://localhost:8080
- url: http://localhost:8080/api/v1
tags:
- name: search
description: Search operations
@ -22,7 +22,7 @@ tags:
- name: suggest
description: Suggest operations
paths:
/json/search:
/documents:
get:
tags:
- search
@ -77,12 +77,6 @@ paths:
items:
type: string
example: [name]
- name: callback
in: query
description: Callback name for using JSONP
required: false
schema:
type: string
- name: facet.field
in: query
description: Facet field name
@ -153,156 +147,157 @@ paths:
schema:
type: string
example: abc
- name: callback
in: query
description: Callback name for using JSONP
required: false
schema:
type: string
responses:
'200':
description: successful operation
description: Successful operation
content:
application/json:
schema:
type: object
properties:
response:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 0
q:
type: string
example: Fess
query_id:
type: string
example: bd60f9579a494dfd8c03db7c8aa905b0
exec_time:
type: number
example: 0.21
query_time:
type: integer
format: int64
example: 0
page_size:
type: integer
example: 20
page_number:
type: integer
example: 1
record_count:
type: integer
format: int64
example: 31625
page_count:
type: integer
example: 1
highlight_params:
type: string
example: "&hq=n2sm&hq=Fess"
next_page:
type: boolean
example: true
prev_page:
type: boolean
example: false
start_record_number:
type: integer
example: 1
end_record_number:
type: integer
example: 20
page_numbers:
type: array
items:
q:
type: string
example: Fess
query_id:
type: string
example: bd60f9579a494dfd8c03db7c8aa905b0
exec_time:
type: number
example: 0.21
query_time:
type: integer
format: int64
example: 0
page_size:
type: integer
example: 20
page_number:
type: integer
example: 1
record_count:
type: integer
format: int64
example: 31625
page_count:
type: integer
example: 1
highlight_params:
type: string
example: "&hq=n2sm&hq=Fess"
next_page:
type: boolean
example: true
prev_page:
type: boolean
example: false
start_record_number:
type: integer
example: 1
end_record_number:
type: integer
example: 20
page_numbers:
type: array
items:
type: string
example: ["1", "2", "3", "4", "5"]
partial:
type: boolean
example: false
search_query:
type: string
example: "(Fess OR n2sm)"
requested_time:
type: integer
format: int64
example: 1507822131845
related_query:
type: array
items:
type: string
example: ["aaa"]
related_contents:
type: array
items:
type: string
example: []
result:
type: array
items:
type: object
properties:
filetype:
type: string
example: ["1", "2", "3", "4", "5"]
partial:
type: boolean
example: false
search_query:
type: string
example: "(Fess OR n2sm)"
requested_time:
type: integer
format: int64
example: 1507822131845
related_query:
type: array
items:
example: html
title:
type: string
example: ["aaa"]
related_contents:
type: array
items:
example: "Open Source Enterprise Search Server: Fess — Fess 11.0 documentation"
content_title:
type: string
example: []
result:
type: array
items:
type: object
properties:
filetype:
type: string
example: html
title:
type: string
example: "Open Source Enterprise Search Server: Fess — Fess 11.0 documentation"
content_title:
type: string
example: "Open Source Enterprise Search Server: Fess — Fe..."
digest:
type: string
example: "Docs » Open Source Enterprise Search Server: Fess Commercial Support Open Source Enterprise Search Server: Fess What is Fess ? Fess is very powerful and easily deployable Enterprise Search Server. ..."
host:
type: string
format: hostname
example: "fess.codelibs.org"
last_modified:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
content_length:
type: string
example: "29624"
timestamp:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
url_link:
type: string
example: "https://fess.codelibs.org/"
created:
type: string
format: date-time
example: "2017-10-10T15:00:48.609Z"
site_path:
type: string
example: "fess.codelibs.org/"
doc_id:
type: string
example: "e79fbfdfb09d4bffb58ec230c68f6f7e"
url:
type: string
format: uri
example: "https://fess.codelibs.org/"
content_description:
type: string
example: "Enterprise Search Server: <strong>Fess</strong> Commercial Support Open...Search Server: <strong>Fess</strong> What is <strong>Fess</strong> ? <strong>Fess</strong> is very powerful...You can install and run <strong>Fess</strong> quickly on any platforms...Java runtime environment. <strong>Fess</strong> is provided under Apache...Apache license. Demo <strong>Fess</strong> is Elasticsearch-based search"
site:
type: string
example: "fess.codelibs.org/"
boost:
type: string
example: "10.0"
mimetype:
type: string
example: "text/html"
example: "Open Source Enterprise Search Server: Fess — Fe..."
digest:
type: string
example: "Docs » Open Source Enterprise Search Server: Fess Commercial Support Open Source Enterprise Search Server: Fess What is Fess ? Fess is very powerful and easily deployable Enterprise Search Server. ..."
host:
type: string
format: hostname
example: "fess.codelibs.org"
last_modified:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
content_length:
type: string
example: "29624"
timestamp:
type: string
format: date-time
example: "2017-10-09T22:28:56.000Z"
url_link:
type: string
example: "https://fess.codelibs.org/"
created:
type: string
format: date-time
example: "2017-10-10T15:00:48.609Z"
site_path:
type: string
example: "fess.codelibs.org/"
doc_id:
type: string
example: "e79fbfdfb09d4bffb58ec230c68f6f7e"
url:
type: string
format: uri
example: "https://fess.codelibs.org/"
content_description:
type: string
example: "Enterprise Search Server: <strong>Fess</strong> Commercial Support Open...Search Server: <strong>Fess</strong> What is <strong>Fess</strong> ? <strong>Fess</strong> is very powerful...You can install and run <strong>Fess</strong> quickly on any platforms...Java runtime environment. <strong>Fess</strong> is provided under Apache...Apache license. Demo <strong>Fess</strong> is Elasticsearch-based search"
site:
type: string
example: "fess.codelibs.org/"
boost:
type: string
example: "10.0"
mimetype:
type: string
example: "text/html"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/json/label:
/labels:
get:
tags:
- search
@ -311,41 +306,36 @@ paths:
operationId: listLabels
responses:
'200':
description: successful operation
description: Successful operation
content:
application/json:
schema:
type: object
properties:
response:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 0
record_count:
type: integer
example: 9
result:
type: array
items:
type: object
properties:
label:
type: string
example: AWS
value:
type: string
example: aws
record_count:
type: integer
example: 9
data:
type: array
items:
type: object
properties:
label:
type: string
example: AWS
value:
type: string
example: aws
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/json/popularword:
/popular-words:
get:
tags:
- popularword
@ -360,9 +350,9 @@ paths:
schema:
type: string
example: 123
- name: labels
- name: label
in: query
description: Labels to fileter results
description: Filtered label name
required: false
style: form
explode: true
@ -371,9 +361,9 @@ paths:
items:
type: string
example: [label]
- name: fields
- name: field
in: query
description: Fields to find results
description: Field name to generate suggest words
required: false
style: form
explode: true
@ -381,38 +371,33 @@ paths:
type: array
items:
type: string
example: [field]
example: [python]
responses:
'200':
description: successful operation
description: Successful operation
content:
application/json:
schema:
type: object
properties:
response:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 0
record_count:
type: integer
example: 9
result:
type: array
items:
type: string
example: ["test"]
record_count:
type: integer
example: 9
data:
type: array
items:
type: string
example: ["python"]
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/json/ping:
/health:
get:
tags:
- monitor
@ -421,36 +406,47 @@ paths:
operationId: ping
responses:
'200':
description: successful operation
description: Successful operation
content:
application/json:
schema:
type: object
properties:
response:
data:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 0
message:
type: object
properties:
status:
type: string
example: green
timed_out:
type: boolean
example: false
type: string
example: green
timed_out:
type: boolean
example: false
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: Service unavailable
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
status:
type: string
example: green
timed_out:
type: boolean
example: false
/suggest:
/suggest-words:
get:
tags:
- suggest
@ -458,7 +454,7 @@ paths:
description: Returns words for suggest
operationId: findSuggestWords
parameters:
- name: query
- name: q
in: query
description: Inputting characters for search
required: true
@ -475,70 +471,78 @@ paths:
exclusiveMinimum: false
example: 10
default: 10
- name: tags
- name: label
in: query
description: Tags to filter results
description: Filtered label name
required: false
style: form
explode: false
explode: true
schema:
type: string
example: "tag1,tag2"
- name: fields
type: array
items:
type: string
example: [label]
- name: field
in: query
description: Fields to find results
description: Field name to generate suggest words
required: false
style: form
explode: false
explode: true
schema:
type: string
example: "field1,field2"
type: array
items:
type: string
example: [python]
- name: lang
in: query
description: Target language
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example: [en]
responses:
'200':
description: successful operation
description: Successful operation
content:
application/json:
schema:
type: object
properties:
response:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 0
result:
type: object
properties:
took:
took:
type: integer
format: int64
example: 18
total:
type: integer
example: 355
num:
type: integer
example: 10
data:
type: array
items:
type: object
properties:
text:
type: string
example: fess
field:
type: array
items:
type: string
example: 18
total:
type: string
example: 355
num:
type: string
example: 10
hits:
type: array
items:
type: object
properties:
text:
type: string
example: fess
tags:
type: array
items:
type: string
example: [java, python]
example: [java, python]
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
responses:
@ -554,20 +558,26 @@ components:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Page not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
type: object
properties:
response:
type: object
properties:
version:
type: string
example: "14.8"
status:
type: integer
example: 1
message:
type: string
example: "error_code:bd6b0bd6-0144-40bc-9567-c5751dd8eecb"
error_code:
type: string
example: "bd6b0bd6-0144-40bc-9567-c5751dd8eecb"
message:
type: string
example: "This is an error message."

View file

@ -35,7 +35,7 @@ public abstract class BaseApiManager implements WebApiManager {
protected String pathPrefix;
protected enum FormatType {
SEARCH, LABEL, POPULARWORD, FAVORITE, FAVORITES, OTHER, PING, SCROLL;
SEARCH, LABEL, POPULARWORD, FAVORITE, FAVORITES, PING, SCROLL, SUGGEST, OTHER;
}
public String getPathPrefix() {
@ -51,6 +51,13 @@ public abstract class BaseApiManager implements WebApiManager {
if (formatType != null) {
return formatType;
}
formatType = detectFormatType(request);
request.setAttribute(API_FORMAT_TYPE, formatType);
return formatType;
}
protected FormatType detectFormatType(final HttpServletRequest request) {
String value = request.getParameter("type");
if (value == null) {
final String servletPath = request.getServletPath();
@ -60,30 +67,30 @@ public abstract class BaseApiManager implements WebApiManager {
}
}
if (value == null) {
formatType = FormatType.SEARCH;
return FormatType.SEARCH;
} else {
final String type = value.toUpperCase(Locale.ROOT);
if (FormatType.SEARCH.name().equals(type)) {
formatType = FormatType.SEARCH;
return FormatType.SEARCH;
} else if (FormatType.LABEL.name().equals(type)) {
formatType = FormatType.LABEL;
return FormatType.LABEL;
} else if (FormatType.POPULARWORD.name().equals(type)) {
formatType = FormatType.POPULARWORD;
return FormatType.POPULARWORD;
} else if (FormatType.FAVORITE.name().equals(type)) {
formatType = FormatType.FAVORITE;
return FormatType.FAVORITE;
} else if (FormatType.FAVORITES.name().equals(type)) {
formatType = FormatType.FAVORITES;
return FormatType.FAVORITES;
} else if (FormatType.PING.name().equals(type)) {
formatType = FormatType.PING;
return FormatType.PING;
} else if (FormatType.SCROLL.name().equals(type)) {
formatType = FormatType.SCROLL;
return FormatType.SCROLL;
} else if (FormatType.SUGGEST.name().equals(type)) {
return FormatType.SUGGEST;
} else {
// default
formatType = FormatType.OTHER;
return FormatType.OTHER;
}
}
request.setAttribute(API_FORMAT_TYPE, formatType);
return formatType;
}
protected void write(final String text, final String contentType, final String encoding) {

View file

@ -39,9 +39,10 @@ import org.codelibs.fess.util.ComponentUtil;
import org.lastaflute.web.util.LaRequestUtil;
import org.lastaflute.web.util.LaResponseUtil;
public abstract class BaseJsonApiManager extends BaseApiManager {
@Deprecated
public abstract class ClassicJsonApiManager extends BaseApiManager {
private static final Logger logger = LogManager.getLogger(BaseJsonApiManager.class);
private static final Logger logger = LogManager.getLogger(ClassicJsonApiManager.class);
protected String mimeType = "application/json";

View file

@ -35,7 +35,7 @@ import org.apache.logging.log4j.Logger;
import org.codelibs.core.exception.IORuntimeException;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseJsonApiManager;
import org.codelibs.fess.api.ClassicJsonApiManager;
import org.codelibs.fess.app.service.FavoriteLogService;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
@ -61,7 +61,8 @@ import org.codelibs.fess.util.FacetResponse.Field;
import org.dbflute.optional.OptionalThing;
import org.opensearch.script.Script;
public class JsonApiManager extends BaseJsonApiManager {
@Deprecated
public class JsonApiManager extends ClassicJsonApiManager {
private static final Logger logger = LogManager.getLogger(JsonApiManager.class);

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.api.BaseJsonApiManager;
import org.codelibs.fess.api.ClassicJsonApiManager;
import org.codelibs.fess.entity.FacetInfo;
import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.HighlightInfo;
@ -49,7 +49,8 @@ import org.codelibs.fess.suggest.request.suggest.SuggestRequestBuilder;
import org.codelibs.fess.suggest.request.suggest.SuggestResponse;
import org.codelibs.fess.util.ComponentUtil;
public class SuggestApiManager extends BaseJsonApiManager {
@Deprecated
public class SuggestApiManager extends ClassicJsonApiManager {
private static final Logger logger = LogManager.getLogger(SuggestApiManager.class);
public SuggestApiManager() {

View file

@ -94,11 +94,11 @@ public abstract class SearchRequestParams {
return stream(values).get(stream -> stream.allMatch(StringUtil::isBlank));
}
protected String[] simplifyArray(final String[] values) {
protected static String[] simplifyArray(final String[] values) {
return stream(values).get(stream -> stream.filter(StringUtil::isNotBlank).distinct().toArray(n -> new String[n]));
}
protected String[] getParamValueArray(final HttpServletRequest request, final String param) {
public static String[] getParamValueArray(final HttpServletRequest request, final String param) {
return simplifyArray(request.getParameterValues(param));
}

View file

@ -7,6 +7,8 @@
<component name="webApiManagerFactory" class="org.codelibs.fess.api.WebApiManagerFactory">
</component>
<component name="searchApiManager" class="org.codelibs.fess.api.json.SearchApiManager">
</component>
<component name="jsonApiManager" class="org.codelibs.fess.api.json.JsonApiManager">
</component>
<component name="searchEngineApiManager" class="org.codelibs.fess.api.engine.SearchEngineApiManager">