fix #405 : customizable default label/sort value

This commit is contained in:
Shinsuke Sugaya 2016-03-01 21:58:15 +09:00
parent b6c52bf6ca
commit 89e09ca567
18 changed files with 171 additions and 50 deletions

View file

@ -111,6 +111,8 @@ public class Constants extends CoreLibConstants {
public static final String DEFAULT_LABEL_VALUE_PROPERTY = "label.value";
public static final String DEFAULT_SORT_VALUE_PROPERTY = "sort.value";
public static final String LOGIN_REQUIRED_PROPERTY = "login.required";
public static final String IGNORE_FAILURE_TYPE_PROPERTY = "failure.ignoretype";

View file

@ -51,9 +51,6 @@ import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.lastaflute.taglib.function.LaFunctions;
public class SearchService {
@ -101,18 +98,9 @@ public class SearchService {
fessConfig.getIndexDocumentSearchIndex(),
fessConfig.getIndexDocumentType(),
searchRequestBuilder -> {
if (StringUtil.isNotBlank(sortField)) {
final String[] sort = sortField.split("\\.");
final SortBuilder sortBuilder = SortBuilders.fieldSort(sort[0]);
if ("asc".equals(sort[1])) {
sortBuilder.order(SortOrder.ASC);
} else if ("desc".equals(sort[1])) {
sortBuilder.order(SortOrder.DESC);
}
searchRequestBuilder.addSort(sortBuilder);
}
return SearchConditionBuilder.builder(searchRequestBuilder).query(query).offset(pageStart).size(pageSize)
.facetInfo(params.getFacetInfo()).geoInfo(params.getGeoInfo())
return SearchConditionBuilder.builder(searchRequestBuilder)
.query(StringUtil.isBlank(sortField) ? query : query + " sort:" + sortField).offset(pageStart)
.size(pageSize).facetInfo(params.getFacetInfo()).geoInfo(params.getGeoInfo())
.responseFields(queryHelper.getResponseFields()).administrativeAccess(params.isAdministrativeAccess())
.build();
}, (searchRequestBuilder, execTime, searchResponse) -> {

View file

@ -44,7 +44,7 @@ public class RootAction extends FessSearchAction {
return asHtml(path_IndexJsp).useForm(SearchForm.class, op -> {
op.setup(form -> {
buildLabelParams(form.fields);
buildFormParams(form);
});
}).renderWith(
data -> {

View file

@ -124,7 +124,8 @@ public class AdminGeneralAction extends FessAdminAction {
updateProperty(Constants.USER_INFO_PROPERTY, getCheckboxValue(form.userInfo));
updateProperty(Constants.USER_FAVORITE_PROPERTY, getCheckboxValue(form.userFavorite));
updateProperty(Constants.WEB_API_JSON_PROPERTY, getCheckboxValue(form.webApiJson));
updateProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, form.defaultLabelValue);
fessConfig.setDefaultLabelValue(form.defaultLabelValue);
fessConfig.setDefaultSortValue(form.defaultSortValue);
updateProperty(Constants.APPEND_QUERY_PARAMETER_PROPERTY, getCheckboxValue(form.appendQueryParameter));
updateProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, form.ignoreFailureType);
updateProperty(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, form.failureCountThreshold.toString());
@ -163,7 +164,8 @@ public class AdminGeneralAction extends FessAdminAction {
form.userInfo = systemProperties.getProperty(Constants.USER_INFO_PROPERTY, Constants.TRUE);
form.userFavorite = systemProperties.getProperty(Constants.USER_FAVORITE_PROPERTY, Constants.FALSE);
form.webApiJson = systemProperties.getProperty(Constants.WEB_API_JSON_PROPERTY, Constants.TRUE);
form.defaultLabelValue = systemProperties.getProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
form.defaultLabelValue = fessConfig.getDefaultLabelValue();
form.defaultSortValue = fessConfig.getDefaultSortValue();
form.appendQueryParameter = systemProperties.getProperty(Constants.APPEND_QUERY_PARAMETER_PROPERTY, Constants.FALSE);
form.ignoreFailureType =
systemProperties.getProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, Constants.DEFAULT_IGNORE_FAILURE_TYPE);

View file

@ -62,6 +62,9 @@ public class EditForm implements Serializable {
@Size(max = 1000)
public String defaultLabelValue;
@Size(max = 1000)
public String defaultSortValue;
@Size(max = 10)
public String appendQueryParameter;

View file

@ -15,7 +15,6 @@
*/
package org.codelibs.fess.app.web.base;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@ -134,25 +133,22 @@ public abstract class FessSearchAction extends FessBaseAction {
return false;
}
protected void buildLabelParams(final Map<String, String[]> fields) {
protected void buildFormParams(final SearchForm form) {
if (form.facet == null) {
form.facet = queryHelper.getDefaultFacetInfo();
}
if (form.geo == null) {
form.geo = queryHelper.getDefaultGeoInfo();
}
// label
final List<Map<String, String>> labelTypeItems = labelTypeHelper.getLabelTypeItemList();
if (!labelTypeItems.isEmpty() && !fields.containsKey(FessSearchAction.LABEL_FIELD)) {
final String defaultLabelValue = systemProperties.getProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
if (StringUtil.isNotBlank(defaultLabelValue)) {
final String[] values = defaultLabelValue.split("\n");
if (values != null && values.length > 0) {
final List<String> list = new ArrayList<String>(values.length);
for (final String value : values) {
if (StringUtil.isNotBlank(value)) {
list.add(value);
}
}
if (!list.isEmpty()) {
fields.put(FessSearchAction.LABEL_FIELD, list.toArray(new String[list.size()]));
}
}
if (!labelTypeItems.isEmpty() && !form.fields.containsKey(FessSearchAction.LABEL_FIELD)) {
final String[] defaultLabelValues = fessConfig.getDefaultLabelValues(getUserBean());
if (defaultLabelValues.length > 0) {
form.fields.put(FessSearchAction.LABEL_FIELD, defaultLabelValues);
}
}
@ -163,6 +159,14 @@ public abstract class FessSearchAction extends FessBaseAction {
}
}
request.setAttribute(Constants.LABEL_VALUE_MAP, labelMap);
// sort
if (StringUtil.isBlank(form.sort)) {
String[] defaultSortValues = fessConfig.getDefaultSortValues(getUserBean());
if (defaultSortValues.length > 0) {
form.sort = String.join(",", defaultSortValues);
}
}
}
protected void buildInitParams() {

View file

@ -47,7 +47,7 @@ public class HelpAction extends FessSearchAction {
return asHtml(path_HelpJsp).useForm(SearchForm.class, op -> {
op.setup(form -> {
buildLabelParams(form.fields);
buildFormParams(form);
});
}).renderWith(data -> {
buildInitParams();

View file

@ -118,8 +118,7 @@ public class SearchAction extends FessSearchAction {
}
try {
updateSearchParams(form);
buildLabelParams(form.fields);
buildFormParams(form);
form.lang = searchService.getLanguages(request, form);
request.setAttribute(Constants.REQUEST_LANGUAGES, form.lang);
final WebRenderData renderData = new WebRenderData();
@ -173,16 +172,6 @@ public class SearchAction extends FessSearchAction {
return doSearch(form);
}
protected void updateSearchParams(final SearchForm form) {
if (form.facet == null) {
form.facet = queryHelper.getDefaultFacetInfo();
}
if (form.geo == null) {
form.geo = queryHelper.getDefaultGeoInfo();
}
}
protected String getDisplayQuery(final SearchForm form, final List<Map<String, String>> labelTypeItems) {
final StringBuilder buf = new StringBuilder(100);
buf.append(form.q);

View file

@ -69,6 +69,8 @@ import org.lastaflute.web.util.LaRequestUtil;
public class QueryHelper implements Serializable {
protected static final String SCORE_SORT_VALUE = "score";
protected static final long serialVersionUID = 1L;
protected static final String SCORE_FIELD = "score";
@ -182,7 +184,7 @@ public class QueryHelper implements Serializable {
}
if (supportedSortFields == null) {
supportedSortFields =
new String[] { fessConfig.getIndexFieldCreated(), fessConfig.getIndexFieldContentLength(),
new String[] { SCORE_SORT_VALUE, fessConfig.getIndexFieldCreated(), fessConfig.getIndexFieldContentLength(),
fessConfig.getIndexFieldLastModified(), fessConfig.getIndexFieldTimestamp(),
fessConfig.getIndexFieldClickCount(), fessConfig.getIndexFieldFavoriteCount() };
}
@ -419,7 +421,7 @@ public class QueryHelper implements Serializable {
} else {
sortOrder = SortOrder.ASC;
}
context.addSorts(SortBuilders.fieldSort(sortField).order(sortOrder));
context.addSorts(SortBuilders.fieldSort(SCORE_SORT_VALUE.equals(sortField) ? "_score" : sortField).order(sortOrder));
return null;
} else if (INURL_FIELD.equals(field)) {
return QueryBuilders.wildcardQuery(fessConfig.getIndexFieldUrl(), "*" + text + "*").boost(termQuery.getBoost());

View file

@ -587,6 +587,9 @@ public class FessLabels extends ActionMessages {
/** The key of the message: -- Results per page -- */
public static final String LABELS_search_result_select_num = "{labels.search_result_select_num}";
/** The key of the message: Score */
public static final String LABELS_search_result_sort_score_desc = "{labels.search_result_sort_score_desc}";
/** The key of the message: Date (ascending) */
public static final String LABELS_search_result_sort_created_asc = "{labels.search_result_sort_created_asc}";
@ -956,6 +959,9 @@ public class FessLabels extends ActionMessages {
/** The key of the message: Default Label Value */
public static final String LABELS_default_label_value = "{labels.default_label_value}";
/** The key of the message: Default Sort Value */
public static final String LABELS_default_sort_value = "{labels.default_sort_value}";
/** The key of the message: Append Params to URL */
public static final String LABELS_append_query_param_enabled = "{labels.append_query_param_enabled}";

View file

@ -31,13 +31,23 @@ import org.codelibs.core.lang.StringUtil;
import org.codelibs.core.misc.Pair;
import org.codelibs.core.misc.Tuple3;
import org.codelibs.fess.Constants;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.StreamUtil;
import org.dbflute.optional.OptionalThing;
import org.lastaflute.job.LaJob;
import org.lastaflute.job.subsidiary.ConcurrentExec;
public interface FessProp {
public static final String GROUP_VALUE_PREFIX = "group:";
public static final String ROLE_VALUE_PREFIX = "role:";
public static final String DEFAULT_SORT_VALUES = "defaultSortValues";
public static final String DEFAULT_LABEL_VALUES = "defaultLabelValues";
public static final String QUERY_LANGUAGE_MAPPING = "queryLanguageMapping";
public static final String CRAWLER_METADATA_NAME_MAPPING = "crawlerMetadataNameMapping";
@ -90,6 +100,98 @@ public interface FessProp {
setSystemProperty(key, Integer.toString(value));
}
public default String[] getDefaultSortValues(final OptionalThing<FessUserBean> userBean) {
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>) propMap.get(DEFAULT_SORT_VALUES);
if (map == null) {
String value = getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY);
if (StringUtil.isBlank(value)) {
map = Collections.emptyMap();
} else {
map = StreamUtil.of(value.split("\n")).filter(s -> StringUtil.isNotBlank(s)).map(s -> {
final String[] pair = s.split("=");
if (pair.length == 1) {
return new Pair<>(StringUtil.EMPTY, pair[0].trim());
} else if (pair.length == 2) {
return new Pair<>(pair[1].trim(), pair[0].trim());
}
return null;
}).filter(o -> o != null).collect(Collectors.toMap(Pair::getFirst, d -> d.getSecond()));
}
propMap.put(DEFAULT_SORT_VALUES, map);
}
return map
.entrySet()
.stream()
.map(e -> {
final String key = e.getKey();
if (StringUtil.isEmpty(key)) {
return e.getValue();
}
if (userBean.map(
user -> StreamUtil.of(user.getRoles()).anyMatch(s -> key.equals(ROLE_VALUE_PREFIX + s))
|| StreamUtil.of(user.getGroups()).anyMatch(s -> key.equals(GROUP_VALUE_PREFIX + s))).orElse(false)) {
return e.getValue();
}
return null;
}).filter(s -> StringUtil.isNotBlank(s)).toArray(n -> new String[n]);
}
public default void setDefaultSortValue(final String value) {
setSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, value);
propMap.remove(DEFAULT_SORT_VALUES);
}
public default String getDefaultSortValue() {
return getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, StringUtil.EMPTY);
}
public default String[] getDefaultLabelValues(final OptionalThing<FessUserBean> userBean) {
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>) propMap.get(DEFAULT_LABEL_VALUES);
if (map == null) {
String value = getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY);
if (StringUtil.isBlank(value)) {
map = Collections.emptyMap();
} else {
map = StreamUtil.of(value.split("\n")).filter(s -> StringUtil.isNotBlank(s)).map(s -> {
final String[] pair = s.split("=");
if (pair.length == 1) {
return new Pair<>(StringUtil.EMPTY, pair[0].trim());
} else if (pair.length == 2) {
return new Pair<>(pair[1].trim(), pair[0].trim());
}
return null;
}).filter(o -> o != null).collect(Collectors.toMap(Pair::getFirst, d -> d.getSecond()));
}
propMap.put(DEFAULT_LABEL_VALUES, map);
}
return map
.entrySet()
.stream()
.map(e -> {
final String key = e.getKey();
if (StringUtil.isEmpty(key)) {
return e.getValue();
}
if (userBean.map(
user -> StreamUtil.of(user.getRoles()).anyMatch(s -> key.equals(ROLE_VALUE_PREFIX + s))
|| StreamUtil.of(user.getGroups()).anyMatch(s -> key.equals(GROUP_VALUE_PREFIX + s))).orElse(false)) {
return e.getValue();
}
return null;
}).filter(s -> StringUtil.isNotBlank(s)).toArray(n -> new String[n]);
}
public default void setDefaultLabelValue(final String value) {
setSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, value);
propMap.remove(DEFAULT_LABEL_VALUES);
}
public default String getDefaultLabelValue() {
return getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
}
public default void setLoginRequired(final boolean value) {
setSystemPropertyAsBoolean(Constants.LOGIN_REQUIRED_PROPERTY, value);
}

View file

@ -189,6 +189,7 @@ labels.search_title=Fess
labels.search_popular_word_word=Popular Words:
labels.search_result_select_sort=-- Sort --
labels.search_result_select_num=-- Results per page --
labels.search_result_sort_score_desc=Score
labels.search_result_sort_created_asc=Date (ascending)
labels.search_result_sort_created_desc=Date (descending)
labels.search_result_sort_content_length_asc=Size (ascending)
@ -315,6 +316,7 @@ labels.user_info_enabled=User Logging
labels.user_favorite_enabled=Favorite Logging
labels.web_api_json_enabled=JSON Response
labels.default_label_value=Default Label Value
labels.default_sort_value=Default Sort Value
labels.append_query_param_enabled=Append Params to URL
labels.login_required=Login Required
labels.ignore_failure_type=Excluded Failure Type

View file

@ -189,6 +189,7 @@ labels.search_title=Fess
labels.search_popular_word_word=Popular Words:
labels.search_result_select_sort=-- Sort --
labels.search_result_select_num=-- Results per page --
labels.search_result_sort_score_desc=Score
labels.search_result_sort_created_asc=Date (ascending)
labels.search_result_sort_created_desc=Date (descending)
labels.search_result_sort_content_length_asc=Size (ascending)
@ -315,6 +316,7 @@ labels.user_info_enabled=User Logging
labels.user_favorite_enabled=Favorite Logging
labels.web_api_json_enabled=JSON Response
labels.default_label_value=Default Label Value
labels.default_sort_value=Default Sort Value
labels.append_query_param_enabled=Append Params to URL
labels.login_required=Login Required
labels.ignore_failure_type=Excluded Failure Type

View file

@ -184,6 +184,7 @@ labels.search_title = Fess
labels.search_popular_word_word = \u4eba\u6c17\u30ef\u30fc\u30c9:
labels.search_result_select_sort = - \u30bd\u30fc\u30c8 -
labels.search_result_select_num = - \u8868\u793a\u4ef6\u6570 -
labels.search_result_sort_score_desc=\u30b9\u30b3\u30a2\u9806
labels.search_result_sort_created_asc = \u65e5\u4ed8 (\u6607\u9806)
labels.search_result_sort_created_desc = \u65e5\u4ed8 (\u964d\u9806)
labels.search_result_sort_content_length_asc = \u30b5\u30a4\u30ba (\u6607\u9806)
@ -310,6 +311,7 @@ labels.user_info_enabled = \u30e6\u30fc\u30b6\u30ed\u30b0
labels.user_favorite_enabled = \u304a\u6c17\u306b\u5165\u308a\u30ed\u30b0
labels.web_api_json_enabled = JSON\u30ec\u30b9\u30dd\u30f3\u30b9
labels.default_label_value = \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30e9\u30d9\u30eb\u5024
labels.default_sort_value = \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30bd\u30fc\u30c8\u5024
labels.append_query_param_enabled = \u691c\u7d22\u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u8ffd\u52a0
labels.login_required = \u30ed\u30b0\u30a4\u30f3\u304c\u5fc5\u8981
labels.ignore_failure_type = \u9664\u5916\u3059\u308b\u30a8\u30e9\u30fc\u306e\u7a2e\u985e

View file

@ -66,6 +66,15 @@
styleClass="form-control" />
</div>
</div>
<div class="form-group">
<label for="defaultSortValue" class="col-sm-3 control-label"><la:message
key="labels.default_sort_value" /></label>
<div class="col-sm-9">
<la:errors property="defaultSortValue" />
<la:textarea property="defaultSortValue"
styleClass="form-control" />
</div>
</div>
<div class="form-group">
<label for="popularWord" class="col-sm-3 control-label"><la:message
key="labels.popular_word_word_enabled" /></label>

View file

@ -76,6 +76,9 @@ ${fe:facetForm()}${fe:geoForm()}
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
<la:option value="score.desc">
<la:message key="labels.search_result_sort_score_desc" />
</la:option>
<la:option value="created.asc">
<la:message key="labels.search_result_sort_created_asc" />
</la:option>

View file

@ -137,6 +137,9 @@
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
<la:option value="score.desc">
<la:message key="labels.search_result_sort_score_desc" />
</la:option>
<la:option value="created.asc">
<la:message key="labels.search_result_sort_created_asc" />
</la:option>

View file

@ -28,6 +28,8 @@
href="#searchOptions" class="label label-primary"
data-toggle="control-options"> <c:if test="${empty sort}">
<la:message key="labels.searchoptions_score" />
</c:if> <c:if test="${sort=='score.desc'}">
<la:message key="labels.searchoptions_score" />
</c:if> <c:if test="${sort=='created.asc'}">
<la:message key="labels.search_result_sort_created_asc" />
</c:if> <c:if test="${sort=='created.desc'}">