add popular words

This commit is contained in:
Shinsuke Sugaya 2015-12-19 16:58:49 +09:00
parent 1a394a16aa
commit 952c63363b
43 changed files with 965 additions and 624 deletions

View file

@ -120,6 +120,10 @@
"type" : "string",
"index" : "not_analyzed"
},
"roles" : {
"type" : "string",
"index" : "not_analyzed"
},
"queryId" : {
"type" : "string",
"index" : "not_analyzed"
@ -188,6 +192,15 @@
"settings" : {
"index" : {
"refresh_interval" : "60s",
"dbflute" : {
"search_log" : {
"properties" : {
"roles" : {
"array" : "true"
}
}
}
},
"number_of_shards" : "10",
"number_of_replicas" : "0"
}

View file

@ -115,7 +115,7 @@ public class Constants extends CoreLibConstants {
public static final String FAILURE_COUNT_THRESHOLD_PROPERTY = "failure.countthreshold";
public static final String WEB_API_HOT_SEARCH_WORD_PROPERTY = "web.api.hotsearch";
public static final String WEB_API_POPULAR_WORD_PROPERTY = "web.api.popularword";
public static final String CSV_FILE_ENCODING_PROPERTY = "csv.file.encoding";

View file

@ -26,18 +26,11 @@ import org.lastaflute.web.util.LaRequestUtil;
import org.lastaflute.web.util.LaResponseUtil;
public abstract class BaseApiManager implements WebApiManager {
protected static final String FAVORITES_API = "/favoritesApi";
protected static final String FAVORITE_API = "/favoriteApi";
protected static final String HOT_SEARCH_WORD_API = "/hotSearchWordApi";
protected static final String SEARCH_API = "/searchApi";
protected String pathPrefix;
protected static enum FormatType {
SEARCH, LABEL, HOTSEARCHWORD, FAVORITE, FAVORITES, OTHER, PING;
SEARCH, LABEL, POPULARWORD, FAVORITE, FAVORITES, OTHER, PING;
}
public String getPathPrefix() {
@ -57,8 +50,8 @@ public abstract class BaseApiManager implements WebApiManager {
return FormatType.SEARCH;
} else if (FormatType.LABEL.name().equals(type)) {
return FormatType.LABEL;
} else if (FormatType.HOTSEARCHWORD.name().equals(type)) {
return FormatType.HOTSEARCHWORD;
} else if (FormatType.POPULARWORD.name().equals(type)) {
return FormatType.POPULARWORD;
} else if (FormatType.FAVORITE.name().equals(type)) {
return FormatType.FAVORITE;
} else if (FormatType.FAVORITES.name().equals(type)) {

View file

@ -46,9 +46,8 @@ import org.codelibs.fess.entity.SearchRenderData;
import org.codelibs.fess.entity.SearchRequestParams;
import org.codelibs.fess.es.client.FessEsClient;
import org.codelibs.fess.exception.WebApiException;
import org.codelibs.fess.helper.HotSearchWordHelper;
import org.codelibs.fess.helper.HotSearchWordHelper.Range;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.PopularWordHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.helper.UserInfoHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
@ -93,8 +92,8 @@ public class JsonApiManager extends BaseApiManager {
case LABEL:
processLabelRequest(request, response, chain);
break;
case HOTSEARCHWORD:
processHotSearchWordRequest(request, response, chain);
case POPULARWORD:
processPopularWordRequest(request, response, chain);
break;
case FAVORITE:
processFavoriteRequest(request, response, chain);
@ -311,20 +310,24 @@ public class JsonApiManager extends BaseApiManager {
}
protected void processHotSearchWordRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
if (Constants.FALSE.equals(crawlerProperties.getProperty(Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY, Constants.TRUE))) {
protected void processPopularWordRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
if (Constants.FALSE.equals(crawlerProperties.getProperty(Constants.WEB_API_POPULAR_WORD_PROPERTY, Constants.TRUE))) {
writeJsonResponse(9, null, "Unsupported operation.");
return;
}
final HotSearchWordHelper hotSearchWordHelper = ComponentUtil.getHotSearchWordHelper();
String seed = request.getParameter("seed");
String[] tags = request.getParameterValues("labels");
String[] fields = request.getParameterValues("fields");
String[] excludes = StringUtil.EMPTY_STRINGS;// TODO
final PopularWordHelper popularWordHelper = ComponentUtil.getPopularWordHelper();
int status = 0;
String errMsg = StringUtil.EMPTY;
final StringBuilder buf = new StringBuilder(255);
try {
final List<String> hotSearchWordList =
hotSearchWordHelper.getHotSearchWordList(Range.parseRange(request.getParameter("range")));
final List<String> hotSearchWordList = popularWordHelper.getWordList(seed, tags, fields, excludes);
buf.append("\"result\":[");
boolean first1 = true;

View file

@ -29,11 +29,13 @@ import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.fess.Constants;
import org.codelibs.fess.api.BaseApiManager;
import org.codelibs.fess.api.json.JsonApiManager;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SuggestHelper;
import org.codelibs.fess.suggest.entity.SuggestItem;
import org.codelibs.fess.suggest.request.suggest.SuggestRequestBuilder;
import org.codelibs.fess.suggest.request.suggest.SuggestResponse;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.StreamUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -59,6 +61,7 @@ public class SuggestApiManager extends BaseApiManager {
int status = 0;
String errMsg = StringUtil.EMPTY;
final StringBuilder buf = new StringBuilder(255);
final RoleQueryHelper roleQueryHelper = ComponentUtil.getRoleQueryHelper();
try {
@ -67,9 +70,8 @@ public class SuggestApiManager extends BaseApiManager {
final SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper();
final SuggestRequestBuilder builder = suggestHelper.suggester().suggest();
builder.setQuery(parameter.getQuery());
for (final String field : parameter.getFields()) {
builder.addField(field);
}
StreamUtil.of(parameter.getFields()).forEach(field -> builder.addField(field));
roleQueryHelper.build().stream().forEach(role -> builder.addRole(role));
builder.setSize(parameter.getNum());
builder.addKind(SuggestItem.Kind.USER.toString());

View file

@ -42,6 +42,7 @@ import org.codelibs.fess.es.client.FessEsClient.SearchConditionBuilder;
import org.codelibs.fess.es.client.FessEsClientException;
import org.codelibs.fess.es.log.exentity.SearchLog;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SearchLogHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.helper.UserInfoHelper;
@ -196,6 +197,7 @@ public class SearchService {
final String query, final int pageStart, final int pageSize, final QueryResponseList queryResponseList) {
final SearchLogHelper searchLogHelper = ComponentUtil.getSearchLogHelper();
final RoleQueryHelper roleQueryHelper = ComponentUtil.getRoleQueryHelper();
final SearchLog searchLog = new SearchLog();
if (Constants.TRUE.equals(crawlerProperties.getProperty(Constants.USER_INFO_PROPERTY, Constants.TRUE))) {
@ -205,6 +207,7 @@ public class SearchService {
}
}
searchLog.setRoles(roleQueryHelper.build().stream().toArray(n -> new String[n]));
searchLog.setQueryId(queryId);
searchLog.setHitCount(queryResponseList.getAllRecordCount());
searchLog.setResponseTime(queryResponseList.getExecTime());

View file

@ -100,7 +100,7 @@ public class AdminGeneralAction extends FessAdminAction {
updateProperty(Constants.SUPPORTED_SEARCH_FEATURE_PROPERTY, form.supportedSearch);
updateProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, form.ignoreFailureType);
updateProperty(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, form.failureCountThreshold.toString());
updateProperty(Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY,
updateProperty(Constants.WEB_API_POPULAR_WORD_PROPERTY,
form.hotSearchWord != null && Constants.ON.equalsIgnoreCase(form.hotSearchWord) ? Constants.TRUE : Constants.FALSE);
updateProperty(Constants.CSV_FILE_ENCODING_PROPERTY, form.csvFileEncoding);
updateProperty(Constants.PURGE_SEARCH_LOG_DAY_PROPERTY, form.purgeSearchLogDay.toString());
@ -133,7 +133,7 @@ public class AdminGeneralAction extends FessAdminAction {
form.ignoreFailureType =
crawlerProperties.getProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, Constants.DEFAULT_IGNORE_FAILURE_TYPE);
form.failureCountThreshold = getPropertyAsInteger(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, Constants.DEFAULT_FAILURE_COUNT);
form.hotSearchWord = crawlerProperties.getProperty(Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY, Constants.TRUE);
form.hotSearchWord = crawlerProperties.getProperty(Constants.WEB_API_POPULAR_WORD_PROPERTY, Constants.TRUE);
form.csvFileEncoding = crawlerProperties.getProperty(Constants.CSV_FILE_ENCODING_PROPERTY, Constants.UTF_8);
form.purgeSearchLogDay =
Integer.parseInt(crawlerProperties.getProperty(Constants.PURGE_SEARCH_LOG_DAY_PROPERTY, Constants.DEFAULT_PURGE_DAY));

View file

@ -33,6 +33,7 @@ import org.codelibs.fess.es.client.FessEsClient;
import org.codelibs.fess.exception.UnsupportedSearchException;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.OpenSearchHelper;
import org.codelibs.fess.helper.PopularWordHelper;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SystemHelper;
@ -77,6 +78,9 @@ public abstract class FessSearchAction extends FessBaseAction {
@Resource
protected OpenSearchHelper openSearchHelper;
@Resource
protected PopularWordHelper popularWordHelper;
@Resource
protected DynamicProperties crawlerProperties;
@ -93,6 +97,7 @@ public abstract class FessSearchAction extends FessBaseAction {
favoriteSupport = Constants.TRUE.equals(crawlerProperties.getProperty(Constants.USER_FAVORITE_PROPERTY, Constants.FALSE));
runtime.registerData("searchLogSupport", searchLogSupport);
runtime.registerData("favoriteSupport", favoriteSupport);
runtime.registerData("popularWords", popularWordHelper.getWordList(null, null, null, null));// TODO parameters
return super.hookBefore(runtime);
}

View file

@ -76,6 +76,7 @@ public abstract class BsSearchLogBhv extends EsAbstractBehavior<SearchLog, Searc
final RESULT result = entityType.newInstance();
result.setAccessType(DfTypeUtil.toString(source.get("accessType")));
result.setUser(DfTypeUtil.toString(source.get("user")));
result.setRoles(toStringArray(source.get("roles")));
result.setQueryId(DfTypeUtil.toString(source.get("queryId")));
result.setClientIp(DfTypeUtil.toString(source.get("clientIp")));
result.setHitCount(DfTypeUtil.toLong(source.get("hitCount")));

View file

@ -43,6 +43,9 @@ public class BsSearchLog extends EsAbstractEntity {
/** user */
protected String user;
/** roles */
protected String[] roles;
/** queryId */
protected String queryId;
@ -109,6 +112,9 @@ public class BsSearchLog extends EsAbstractEntity {
if (user != null) {
sourceMap.put("user", user);
}
if (roles != null) {
sourceMap.put("roles", roles);
}
if (queryId != null) {
sourceMap.put("queryId", queryId);
}
@ -159,6 +165,7 @@ public class BsSearchLog extends EsAbstractEntity {
StringBuilder sb = new StringBuilder();
sb.append(dm).append(accessType);
sb.append(dm).append(user);
sb.append(dm).append(roles);
sb.append(dm).append(queryId);
sb.append(dm).append(clientIp);
sb.append(dm).append(hitCount);
@ -202,6 +209,16 @@ public class BsSearchLog extends EsAbstractEntity {
this.user = value;
}
public String[] getRoles() {
checkSpecifiedProperty("roles");
return roles;
}
public void setRoles(String[] value) {
registerModifiedProperty("roles");
this.roles = value;
}
public String getQueryId() {
checkSpecifiedProperty("queryId");
return convertEmptyToNull(queryId);

View file

@ -82,6 +82,7 @@ public class SearchLogDbm extends AbstractDBMeta {
setupEpg(_epgMap, et -> ((SearchLog) et).getAccessType(), (et, vl) -> ((SearchLog) et).setAccessType(DfTypeUtil.toString(vl)),
"accessType");
setupEpg(_epgMap, et -> ((SearchLog) et).getUser(), (et, vl) -> ((SearchLog) et).setUser(DfTypeUtil.toString(vl)), "user");
setupEpg(_epgMap, et -> ((SearchLog) et).getRoles(), (et, vl) -> ((SearchLog) et).setRoles((String[]) vl), "roles");
setupEpg(_epgMap, et -> ((SearchLog) et).getQueryId(), (et, vl) -> ((SearchLog) et).setQueryId(DfTypeUtil.toString(vl)), "queryId");
setupEpg(_epgMap, et -> ((SearchLog) et).getClientIp(), (et, vl) -> ((SearchLog) et).setClientIp(DfTypeUtil.toString(vl)),
"clientIp");
@ -145,6 +146,8 @@ public class SearchLogDbm extends AbstractDBMeta {
false, false, "String", 0, 0, null, false, null, null, null, null, null, false);
protected final ColumnInfo _columnUser = cci("user", "user", null, null, String.class, "user", null, false, false, false, "String", 0,
0, null, false, null, null, null, null, null, false);
protected final ColumnInfo _columnRoles = cci("roles", "roles", null, null, String[].class, "roles", null, false, false, false,
"String", 0, 0, null, false, null, null, null, null, null, false);
protected final ColumnInfo _columnQueryId = cci("queryId", "queryId", null, null, String.class, "queryId", null, false, false, false,
"String", 0, 0, null, false, null, null, null, null, null, false);
protected final ColumnInfo _columnClientIp = cci("clientIp", "clientIp", null, null, String.class, "clientIp", null, false, false,
@ -180,6 +183,10 @@ public class SearchLogDbm extends AbstractDBMeta {
return _columnUser;
}
public ColumnInfo columnRoles() {
return _columnRoles;
}
public ColumnInfo columnQueryId() {
return _columnQueryId;
}
@ -236,6 +243,7 @@ public class SearchLogDbm extends AbstractDBMeta {
List<ColumnInfo> ls = newArrayList();
ls.add(columnAccessType());
ls.add(columnUser());
ls.add(columnRoles());
ls.add(columnQueryId());
ls.add(columnClientIp());
ls.add(columnHitCount());

View file

@ -166,6 +166,10 @@ public class BsSearchLogCB extends EsAbstractConditionBean {
doColumn("user");
}
public void columnRoles() {
doColumn("roles");
}
public void columnQueryId() {
doColumn("queryId");
}

View file

@ -507,6 +507,172 @@ public abstract class BsSearchLogCQ extends EsAbstractConditionQuery {
return this;
}
public void setRoles_Equal(String roles) {
setRoles_Term(roles, null);
}
public void setRoles_Equal(String roles, ConditionOptionCall<TermQueryBuilder> opLambda) {
setRoles_Term(roles, opLambda);
}
public void setRoles_Term(String roles) {
setRoles_Term(roles, null);
}
public void setRoles_Term(String roles, ConditionOptionCall<TermQueryBuilder> opLambda) {
TermQueryBuilder builder = regTermQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_NotEqual(String roles) {
setRoles_NotTerm(roles, null);
}
public void setRoles_NotEqual(String roles, ConditionOptionCall<NotQueryBuilder> opLambda) {
setRoles_NotTerm(roles, opLambda);
}
public void setRoles_NotTerm(String roles) {
setRoles_NotTerm(roles, null);
}
public void setRoles_NotTerm(String roles, ConditionOptionCall<NotQueryBuilder> opLambda) {
NotQueryBuilder builder = QueryBuilders.notQuery(regTermQ("roles", roles));
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_Terms(Collection<String> rolesList) {
setRoles_Terms(rolesList, null);
}
public void setRoles_Terms(Collection<String> rolesList, ConditionOptionCall<TermsQueryBuilder> opLambda) {
TermsQueryBuilder builder = regTermsQ("roles", rolesList);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_InScope(Collection<String> rolesList) {
setRoles_Terms(rolesList, null);
}
public void setRoles_InScope(Collection<String> rolesList, ConditionOptionCall<TermsQueryBuilder> opLambda) {
setRoles_Terms(rolesList, opLambda);
}
public void setRoles_Match(String roles) {
setRoles_Match(roles, null);
}
public void setRoles_Match(String roles, ConditionOptionCall<MatchQueryBuilder> opLambda) {
MatchQueryBuilder builder = regMatchQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_MatchPhrase(String roles) {
setRoles_MatchPhrase(roles, null);
}
public void setRoles_MatchPhrase(String roles, ConditionOptionCall<MatchQueryBuilder> opLambda) {
MatchQueryBuilder builder = regMatchPhraseQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_MatchPhrasePrefix(String roles) {
setRoles_MatchPhrasePrefix(roles, null);
}
public void setRoles_MatchPhrasePrefix(String roles, ConditionOptionCall<MatchQueryBuilder> opLambda) {
MatchQueryBuilder builder = regMatchPhrasePrefixQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_Fuzzy(String roles) {
setRoles_Fuzzy(roles, null);
}
public void setRoles_Fuzzy(String roles, ConditionOptionCall<FuzzyQueryBuilder> opLambda) {
FuzzyQueryBuilder builder = regFuzzyQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_Prefix(String roles) {
setRoles_Prefix(roles, null);
}
public void setRoles_Prefix(String roles, ConditionOptionCall<PrefixQueryBuilder> opLambda) {
PrefixQueryBuilder builder = regPrefixQ("roles", roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_GreaterThan(String roles) {
setRoles_GreaterThan(roles, null);
}
public void setRoles_GreaterThan(String roles, ConditionOptionCall<RangeQueryBuilder> opLambda) {
RangeQueryBuilder builder = regRangeQ("roles", ConditionKey.CK_GREATER_THAN, roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_LessThan(String roles) {
setRoles_LessThan(roles, null);
}
public void setRoles_LessThan(String roles, ConditionOptionCall<RangeQueryBuilder> opLambda) {
RangeQueryBuilder builder = regRangeQ("roles", ConditionKey.CK_LESS_THAN, roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_GreaterEqual(String roles) {
setRoles_GreaterEqual(roles, null);
}
public void setRoles_GreaterEqual(String roles, ConditionOptionCall<RangeQueryBuilder> opLambda) {
RangeQueryBuilder builder = regRangeQ("roles", ConditionKey.CK_GREATER_EQUAL, roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public void setRoles_LessEqual(String roles) {
setRoles_LessEqual(roles, null);
}
public void setRoles_LessEqual(String roles, ConditionOptionCall<RangeQueryBuilder> opLambda) {
RangeQueryBuilder builder = regRangeQ("roles", ConditionKey.CK_LESS_EQUAL, roles);
if (opLambda != null) {
opLambda.callback(builder);
}
}
public BsSearchLogCQ addOrderBy_Roles_Asc() {
regOBA("roles");
return this;
}
public BsSearchLogCQ addOrderBy_Roles_Desc() {
regOBD("roles");
return this;
}
public void setQueryId_Equal(String queryId) {
setQueryId_Term(queryId, null);
}

View file

@ -1,98 +0,0 @@
/*
* Copyright 2012-2015 CodeLibs Project and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.codelibs.fess.helper;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.codelibs.fess.Constants;
import org.codelibs.fess.es.log.exbhv.SearchLogBhv;
import org.codelibs.fess.util.ComponentUtil;
public class HotSearchWordHelper {
@Resource
protected SearchLogBhv searchLogBhv;
protected Map<Range, List<String>> cacheMap = new ConcurrentHashMap<HotSearchWordHelper.Range, List<String>>();
public int size = 10;
public Pattern excludedWordPattern;
@PostConstruct
public void init() {
final long now = ComponentUtil.getSystemHelper().getCurrentTimeAsLong();
cacheMap.put(Range.ONE_DAY, getHotSearchWordListByFromDate(now - Constants.ONE_DAY_IN_MILLIS));
cacheMap.put(Range.ONE_WEEK, getHotSearchWordListByFromDate(now - Constants.ONE_DAY_IN_MILLIS * 7));
cacheMap.put(Range.ONE_MONTH, getHotSearchWordListByFromDate(now - Constants.ONE_DAY_IN_MILLIS * 30));
cacheMap.put(Range.ONE_YEAR, getHotSearchWordListByFromDate(now - Constants.ONE_DAY_IN_MILLIS * 365));
cacheMap.put(Range.ENTIRE, getHotSearchWordListByFromDate(null));
}
protected List<String> getHotSearchWordListByFromDate(final Long fromDate) {
final List<String> wordList = new ArrayList<String>();
// TODO
return wordList;
}
public void reload() {
init();
}
public List<String> getHotSearchWordList(final Range range) {
return cacheMap.get(range);
}
public enum Range {
ONE_DAY(1), ONE_WEEK(7), ONE_MONTH(30), ONE_YEAR(365), ENTIRE(0);
private final long time;
private Range(final long t) {
time = t * Constants.ONE_DAY_IN_MILLIS;
}
public long getTime() {
return time;
}
public static Range parseRange(final String value) {
Range range;
if (value == null) {
range = Range.ENTIRE;
} else if ("day".equals(value) || "1".equals(value)) {
range = Range.ONE_DAY;
} else if ("week".equals(value) || "7".equals(value)) {
range = Range.ONE_DAY;
} else if ("month".equals(value) || "30".equals(value)) {
range = Range.ONE_DAY;
} else if ("year".equals(value) || "365".equals(value)) {
range = Range.ONE_DAY;
} else {
range = Range.ENTIRE;
}
return range;
}
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright 2012-2015 CodeLibs Project and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.codelibs.fess.helper;
import java.util.ArrayList;
import java.util.List;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.suggest.request.popularwords.PopularWordsRequestBuilder;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.StreamUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PopularWordHelper {
private static final Logger logger = LoggerFactory.getLogger(PopularWordHelper.class);
public List<String> getWordList(String seed, String[] tags, String[] fields, String[] excludes) {
RoleQueryHelper roleQueryHelper = ComponentUtil.getRoleQueryHelper();
String[] roles = roleQueryHelper.build().stream().toArray(n -> new String[n]);
return getWordList(seed, tags, roles, fields, excludes);
}
public List<String> getWordList(String seed, String[] tags, String[] roles, String[] fields, String[] excludes) {
// TODO cache
final List<String> wordList = new ArrayList<String>();
FessConfig fessConfig = ComponentUtil.getFessConfig();
SuggestHelper suggestHelper = ComponentUtil.getSuggestHelper();
final PopularWordsRequestBuilder popularWordsRequestBuilder =
suggestHelper.suggester().popularWords().setSize(fessConfig.getSuggestPopularWordSizeAsInteger().intValue())
.setWindowSize(fessConfig.getSuggestPopularWordWindowSizeAsInteger().intValue());
if (seed != null) {
popularWordsRequestBuilder.setSeed(seed);
}
StreamUtil.of(tags).forEach(tag -> popularWordsRequestBuilder.addTag(tag));
StreamUtil.of(roles).forEach(role -> popularWordsRequestBuilder.addRole(role));
StreamUtil.of(fields).forEach(field -> popularWordsRequestBuilder.addField(field));
StreamUtil.of(excludes).forEach(exclude -> popularWordsRequestBuilder.addExcludeWord(exclude));
popularWordsRequestBuilder.execute().then(r -> {
r.getItems().stream().forEach(item -> wordList.add(item.getText()));
}).error(t -> logger.warn("Failed to generate popular words.", t));
return wordList;
}
}

View file

@ -20,9 +20,13 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@ -43,6 +47,7 @@ import org.codelibs.fess.suggest.index.contents.document.ESSourceReader;
import org.codelibs.fess.suggest.settings.SuggestSettings;
import org.codelibs.fess.suggest.util.SuggestUtil;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.StreamUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
@ -51,6 +56,8 @@ import org.slf4j.LoggerFactory;
public class SuggestHelper {
private static final Logger logger = LoggerFactory.getLogger(SuggestHelper.class);
private static final String TEXT_SEP = " ";
@Resource
protected ElevateWordBhv elevateWordBhv;
@ -60,34 +67,39 @@ public class SuggestHelper {
@Resource
protected FessEsClient fessEsClient;
public String[] contentFieldNames = { "_default" };
public String[] tagFieldNames = { "label" };
public String[] roleFieldNames = { "role" };
public String[] contentsIndexFieldNames = { "content", "title" };
public long updateRequestIntervalMills = 1;
public int sourceReaderScrollSize = 1;
private static final String TEXT_SEP = " ";
protected Suggester suggester;
protected final AtomicBoolean initialized = new AtomicBoolean(false);
private FessConfig fessConfig;
private final Set<String> contentFieldNameSet = new HashSet<>();
private final Set<String> tagFieldNameSet = new HashSet<>();
private final Set<String> roleFieldNameSet = new HashSet<>();
private List<String> contentFieldList;
private List<Pattern> roleFilterList = new ArrayList<>();
@PostConstruct
public void init() {
fessConfig = ComponentUtil.getFessConfig();
stream(fessConfig.getSuggestFieldContents()).forEach(f -> contentFieldNameSet.add(f));
stream(fessConfig.getSuggestFieldTags()).forEach(f -> tagFieldNameSet.add(f));
stream(fessConfig.getSuggestFieldRoles()).forEach(f -> roleFieldNameSet.add(f));
contentFieldList = Arrays.asList(stream(fessConfig.getSuggestFieldContents()).toArray(n -> new String[n]));
stream(fessConfig.getSuggestRoleFilters()).forEach(filter -> {
roleFilterList.add(Pattern.compile(filter));
});
final Thread th = new Thread(() -> {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
fessEsClient.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
suggester = Suggester.builder().build(fessEsClient, fessConfig.getIndexDocumentSearchIndex());
suggester.settings().array().delete(SuggestSettings.DefaultKeys.SUPPORTED_FIELDS);
for (final String field : contentsIndexFieldNames) {
stream(fessConfig.getSuggestFieldIndexContents()).forEach(field -> {
suggester.settings().array().add(SuggestSettings.DefaultKeys.SUPPORTED_FIELDS, field);
}
});
suggester.createIndexIfNothing();
initialized.set(true);
});
@ -99,34 +111,41 @@ public class SuggestHelper {
}
public void indexFromSearchLog(final List<SearchLog> searchLogList) {
for (final SearchLog searchLog : searchLogList) {
// TODO if(getHitCount == 0) continue;
final StringBuilder sb = new StringBuilder();
final List<String> fields = new ArrayList<>();
final List<String> tags = new ArrayList<>();
final List<String> roles = new ArrayList<>();
for (final SearchFieldLog searchFieldLog : searchLog.getSearchFieldLogList()) {
final String name = searchFieldLog.getName();
if (isContentField(name)) {
if (sb.length() > 0) {
sb.append(TEXT_SEP);
searchLogList.stream().forEach(
searchLog -> {
if (searchLog.getHitCount() == null
|| searchLog.getHitCount().longValue() < fessConfig.getSuggestMinHitCountAsInteger().longValue()) {
return;
}
sb.append(searchFieldLog.getValue());
fields.add(name);
} else if (isTagField(name)) {
tags.add(searchFieldLog.getValue());
} else if (isRoleField(name)) {
roles.add(searchFieldLog.getValue());
}
}
if (sb.length() > 0) {
suggester.indexer().indexFromSearchWord(sb.toString(), fields.toArray(new String[fields.size()]),
tags.toArray(new String[tags.size()]), roles.toArray(new String[roles.size()]), 1);
}
}
final StringBuilder sb = new StringBuilder();
final List<String> fields = new ArrayList<>();
final List<String> tags = new ArrayList<>();
final List<String> roles = new ArrayList<>();
for (final SearchFieldLog searchFieldLog : searchLog.getSearchFieldLogList()) {
final String name = searchFieldLog.getName();
if (contentFieldNameSet.contains(name)) {
if (sb.length() > 0) {
sb.append(TEXT_SEP);
}
sb.append(searchFieldLog.getValue());
fields.add(name);
} else if (tagFieldNameSet.contains(name)) {
tags.add(searchFieldLog.getValue());
} else if (roleFieldNameSet.contains(name)) {
roles.add(searchFieldLog.getValue());
}
}
if (sb.length() > 0) {
StreamUtil.of(searchLog.getRoles()).forEach(role -> roles.add(role));
if (roles.stream().allMatch(v -> roleFilterList.stream().anyMatch(pattern -> pattern.matcher(v).matches()))) {
suggester.indexer().indexFromSearchWord(sb.toString(), fields.toArray(new String[fields.size()]),
tags.toArray(new String[tags.size()]), roles.toArray(new String[roles.size()]), 1);
}
}
});
suggester.refresh();
}
@ -144,11 +163,12 @@ public class SuggestHelper {
final ESSourceReader reader =
new ESSourceReader(fessEsClient, suggester.settings(), fessConfig.getIndexDocumentSearchIndex(),
fessConfig.getIndexDocumentType());
reader.setScrollSize(sourceReaderScrollSize);
suggester.indexer().indexFromDocument(reader, 2, updateRequestIntervalMills).then(response -> {
suggester.refresh();
success.accept(true);
}).error(t -> error.accept(t));
reader.setScrollSize(fessConfig.getSuggestSourceReaderScrollSizeAsInteger().intValue());
suggester.indexer().indexFromDocument(reader, 2, fessConfig.getSuggestUpdateRequestIntervalAsInteger().longValue())
.then(response -> {
suggester.refresh();
success.accept(true);
}).error(t -> error.accept(t));
}
public void purgeDocumentSuggest(final LocalDateTime time) {
@ -227,8 +247,8 @@ public class SuggestHelper {
}
suggester.indexer().addElevateWord(
new org.codelibs.fess.suggest.entity.ElevateWord(word, boost, Collections.singletonList(reading), Arrays
.asList(contentFieldNames), labelList, roleList));
new org.codelibs.fess.suggest.entity.ElevateWord(word, boost, Collections.singletonList(reading), contentFieldList,
labelList, roleList));
}
public void deleteAllBadWords() {
@ -254,30 +274,8 @@ public class SuggestHelper {
suggester.indexer().deleteBadWord(badWord);
}
protected boolean isContentField(final String field) {
for (final String contentField : contentFieldNames) {
if (contentField.equals(field)) {
return true;
}
}
return false;
private Stream<String> stream(String value) {
return StreamUtil.of(value.split(",")).filter(v -> StringUtil.isNotBlank(v));
}
protected boolean isTagField(final String field) {
for (final String tagField : tagFieldNames) {
if (tagField.equals(field)) {
return true;
}
}
return false;
}
protected boolean isRoleField(final String field) {
for (final String roleField : roleFieldNames) {
if (roleField.equals(field)) {
return true;
}
}
return false;
}
}

View file

@ -59,10 +59,6 @@ public class SystemHelper implements Serializable {
private final Set<String> adminRoleSet = new HashSet<>();
private String[] crawlerJavaOptions = new String[] { "-Djava.awt.headless=true", "-server", "-Xmx256m", "-XX:MaxMetaspaceSize=128m",
"-XX:CompressedClassSpaceSize=32m", "-XX:-UseGCOverheadLimit", "-XX:+UseConcMarkSweepGC",
"-XX:CMSInitiatingOccupancyFraction=75", "-XX:+UseParNewGC", "-XX:+UseTLAB", "-XX:+DisableExplicitGC" };
private String javaCommandPath = "java";
private String filterPathEncoding = Constants.UTF_8;
@ -221,14 +217,6 @@ public class SystemHelper implements Serializable {
return roleList;
}
public String[] getCrawlerJavaOptions() {
return crawlerJavaOptions;
}
public void setCrawlerJavaOptions(final String[] crawlerJavaOptions) {
this.crawlerJavaOptions = crawlerJavaOptions;
}
public String getJavaCommandPath() {
return javaCommandPath;
}

View file

@ -32,9 +32,11 @@ import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.exec.Crawler;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.InputStreamThread;
import org.codelibs.fess.util.JobProcess;
import org.codelibs.fess.util.StreamUtil;
import org.lastaflute.di.core.SingletonLaContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -223,16 +225,17 @@ public class CrawlJob {
}
protected void executeCrawler() {
final List<String> crawlerCmdList = new ArrayList<String>();
final List<String> cmdList = new ArrayList<String>();
final String cpSeparator = SystemUtils.IS_OS_WINDOWS ? ";" : ":";
final ServletContext servletContext = SingletonLaContainer.getComponent(ServletContext.class);
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
final JobHelper jobHelper = ComponentUtil.getJobHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
crawlerCmdList.add(systemHelper.getJavaCommandPath());
cmdList.add(systemHelper.getJavaCommandPath());
// -cp
crawlerCmdList.add("-cp");
cmdList.add("-cp");
final StringBuilder buf = new StringBuilder();
final String confPath = System.getProperty(Constants.FESS_CONF_PATH);
if (StringUtil.isNotBlank(confPath)) {
@ -267,41 +270,38 @@ public class CrawlJob {
if (targetLibDir.isDirectory()) {
appendJarFile(cpSeparator, buf, targetLibDir, targetLibDir.getAbsolutePath() + File.separator);
}
crawlerCmdList.add(buf.toString());
cmdList.add(buf.toString());
if (useLocaleElasticsearch) {
final String transportAddresses = System.getProperty(Constants.FESS_ES_TRANSPORT_ADDRESSES);
if (StringUtil.isNotBlank(transportAddresses)) {
crawlerCmdList.add("-D" + Constants.FESS_ES_TRANSPORT_ADDRESSES + "=" + transportAddresses);
cmdList.add("-D" + Constants.FESS_ES_TRANSPORT_ADDRESSES + "=" + transportAddresses);
}
final String clusterName = System.getProperty(Constants.FESS_ES_CLUSTER_NAME);
if (StringUtil.isNotBlank(clusterName)) {
crawlerCmdList.add("-D" + Constants.FESS_ES_CLUSTER_NAME + "=" + clusterName);
cmdList.add("-D" + Constants.FESS_ES_CLUSTER_NAME + "=" + clusterName);
}
}
final String lastaEnv = System.getProperty("lasta.env");
if (StringUtil.isNotBlank(lastaEnv)) {
if (lastaEnv.equals("web")) {
crawlerCmdList.add("-Dlasta.env=crawler");
cmdList.add("-Dlasta.env=crawler");
} else {
crawlerCmdList.add("-Dlasta.env=" + lastaEnv);
cmdList.add("-Dlasta.env=" + lastaEnv);
}
}
crawlerCmdList.add("-Dfess.crawler.process=true");
crawlerCmdList.add("-Dfess.log.path=" + (logFilePath != null ? logFilePath : systemHelper.getLogFilePath()));
addSystemProperty(crawlerCmdList, "fess.log.name", "fess-crawler", "-crawler");
cmdList.add("-Dfess.crawler.process=true");
cmdList.add("-Dfess.log.path=" + (logFilePath != null ? logFilePath : systemHelper.getLogFilePath()));
addSystemProperty(cmdList, "fess.log.name", "fess-crawler", "-crawler");
if (logLevel == null) {
addSystemProperty(crawlerCmdList, "fess.log.level", null, null);
addSystemProperty(cmdList, "fess.log.level", null, null);
} else {
crawlerCmdList.add("-Dfess.log.level=" + logLevel);
}
if (systemHelper.getCrawlerJavaOptions() != null) {
for (final String value : systemHelper.getCrawlerJavaOptions()) {
crawlerCmdList.add(value);
}
cmdList.add("-Dfess.log.level=" + logLevel);
}
StreamUtil.of(fessConfig.getJvmCrawlerOptions().split("\n")).filter(value -> StringUtil.isNotBlank(value))
.forEach(value -> cmdList.add(value));
File ownTmpDir = null;
if (systemHelper.isUseOwnTmpDir()) {
@ -309,48 +309,48 @@ public class CrawlJob {
if (StringUtil.isNotBlank(tmpDir)) {
ownTmpDir = new File(tmpDir, "fessTmpDir_" + sessionId);
if (ownTmpDir.mkdirs()) {
crawlerCmdList.add("-Djava.io.tmpdir=" + ownTmpDir.getAbsolutePath());
cmdList.add("-Djava.io.tmpdir=" + ownTmpDir.getAbsolutePath());
} else {
ownTmpDir = null;
}
}
}
crawlerCmdList.add(Crawler.class.getCanonicalName());
cmdList.add(Crawler.class.getCanonicalName());
crawlerCmdList.add("--sessionId");
crawlerCmdList.add(sessionId);
crawlerCmdList.add("--name");
crawlerCmdList.add(namespace);
cmdList.add("--sessionId");
cmdList.add(sessionId);
cmdList.add("--name");
cmdList.add(namespace);
if (webConfigIds != null && webConfigIds.length > 0) {
crawlerCmdList.add("-w");
crawlerCmdList.add(StringUtils.join(webConfigIds, ','));
cmdList.add("-w");
cmdList.add(StringUtils.join(webConfigIds, ','));
}
if (fileConfigIds != null && fileConfigIds.length > 0) {
crawlerCmdList.add("-f");
crawlerCmdList.add(StringUtils.join(fileConfigIds, ','));
cmdList.add("-f");
cmdList.add(StringUtils.join(fileConfigIds, ','));
}
if (dataConfigIds != null && dataConfigIds.length > 0) {
crawlerCmdList.add("-d");
crawlerCmdList.add(StringUtils.join(dataConfigIds, ','));
cmdList.add("-d");
cmdList.add(StringUtils.join(dataConfigIds, ','));
}
if (StringUtil.isNotBlank(operation)) {
crawlerCmdList.add("-o");
crawlerCmdList.add(operation);
cmdList.add("-o");
cmdList.add(operation);
}
if (documentExpires >= -1) {
crawlerCmdList.add("-e");
crawlerCmdList.add(Integer.toString(documentExpires));
cmdList.add("-e");
cmdList.add(Integer.toString(documentExpires));
}
final File baseDir = new File(servletContext.getRealPath("/WEB-INF")).getParentFile();
if (logger.isInfoEnabled()) {
logger.info("Crawler: \nDirectory=" + baseDir + "\nOptions=" + crawlerCmdList);
logger.info("Crawler: \nDirectory=" + baseDir + "\nOptions=" + cmdList);
}
final ProcessBuilder pb = new ProcessBuilder(crawlerCmdList);
final ProcessBuilder pb = new ProcessBuilder(cmdList);
pb.directory(baseDir);
pb.redirectErrorStream(true);

View file

@ -31,9 +31,11 @@ import org.codelibs.fess.exception.FessSystemException;
import org.codelibs.fess.exec.SuggestCreator;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.SystemHelper;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.util.InputStreamThread;
import org.codelibs.fess.util.JobProcess;
import org.codelibs.fess.util.StreamUtil;
import org.lastaflute.di.core.SingletonLaContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -93,16 +95,17 @@ public class SuggestJob {
}
protected void executeSuggestCreator() {
final List<String> suggestCreatorCmdList = new ArrayList<>();
final List<String> cmdList = new ArrayList<>();
final String cpSeparator = SystemUtils.IS_OS_WINDOWS ? ";" : ":";
final ServletContext servletContext = SingletonLaContainer.getComponent(ServletContext.class);
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
final JobHelper jobHelper = ComponentUtil.getJobHelper();
final FessConfig fessConfig = ComponentUtil.getFessConfig();
suggestCreatorCmdList.add(systemHelper.getJavaCommandPath());
cmdList.add(systemHelper.getJavaCommandPath());
// -cp
suggestCreatorCmdList.add("-cp");
cmdList.add("-cp");
final StringBuilder buf = new StringBuilder();
final String confPath = System.getProperty(Constants.FESS_CONF_PATH);
if (StringUtil.isNotBlank(confPath)) {
@ -137,41 +140,38 @@ public class SuggestJob {
if (targetLibDir.isDirectory()) {
appendJarFile(cpSeparator, buf, targetLibDir, targetLibDir.getAbsolutePath() + File.separator);
}
suggestCreatorCmdList.add(buf.toString());
cmdList.add(buf.toString());
if (useLocaleElasticsearch) {
final String transportAddresses = System.getProperty(Constants.FESS_ES_TRANSPORT_ADDRESSES);
if (StringUtil.isNotBlank(transportAddresses)) {
suggestCreatorCmdList.add("-D" + Constants.FESS_ES_TRANSPORT_ADDRESSES + "=" + transportAddresses);
cmdList.add("-D" + Constants.FESS_ES_TRANSPORT_ADDRESSES + "=" + transportAddresses);
}
final String clusterName = System.getProperty(Constants.FESS_ES_CLUSTER_NAME);
if (StringUtil.isNotBlank(clusterName)) {
suggestCreatorCmdList.add("-D" + Constants.FESS_ES_CLUSTER_NAME + "=" + clusterName);
cmdList.add("-D" + Constants.FESS_ES_CLUSTER_NAME + "=" + clusterName);
}
}
final String lastaEnv = System.getProperty("lasta.env");
if (StringUtil.isNotBlank(lastaEnv)) {
if (lastaEnv.equals("web")) {
suggestCreatorCmdList.add("-Dlasta.env=suggest");
cmdList.add("-Dlasta.env=suggest");
} else {
suggestCreatorCmdList.add("-Dlasta.env=" + lastaEnv);
cmdList.add("-Dlasta.env=" + lastaEnv);
}
}
suggestCreatorCmdList.add("-Dfess.suggest.process=true");
cmdList.add("-Dfess.suggest.process=true");
if (logFilePath == null) {
final String value = System.getProperty("fess.log.path");
logFilePath = value != null ? value : new File(targetDir, "logs").getAbsolutePath();
}
suggestCreatorCmdList.add("-Dfess.log.path=" + logFilePath);
addSystemProperty(suggestCreatorCmdList, "fess.log.name", "fess-suggest", "-suggest");
addSystemProperty(suggestCreatorCmdList, "fess.log.level", null, null);
if (systemHelper.getCrawlerJavaOptions() != null) {
for (final String value : systemHelper.getCrawlerJavaOptions()) {
suggestCreatorCmdList.add(value);
}
}
cmdList.add("-Dfess.log.path=" + logFilePath);
addSystemProperty(cmdList, "fess.log.name", "fess-suggest", "-suggest");
addSystemProperty(cmdList, "fess.log.level", null, null);
StreamUtil.of(fessConfig.getJvmSuggestOptions().split("\n")).filter(value -> StringUtil.isNotBlank(value))
.forEach(value -> cmdList.add(value));
File ownTmpDir = null;
if (systemHelper.isUseOwnTmpDir()) {
@ -179,25 +179,25 @@ public class SuggestJob {
if (StringUtil.isNotBlank(tmpDir)) {
ownTmpDir = new File(tmpDir, "fessTmpDir_" + sessionId);
if (ownTmpDir.mkdirs()) {
suggestCreatorCmdList.add("-Djava.io.tmpdir=" + ownTmpDir.getAbsolutePath());
cmdList.add("-Djava.io.tmpdir=" + ownTmpDir.getAbsolutePath());
} else {
ownTmpDir = null;
}
}
}
suggestCreatorCmdList.add(SuggestCreator.class.getCanonicalName());
cmdList.add(SuggestCreator.class.getCanonicalName());
suggestCreatorCmdList.add("--sessionId");
suggestCreatorCmdList.add(sessionId);
cmdList.add("--sessionId");
cmdList.add(sessionId);
final File baseDir = new File(servletContext.getRealPath("/WEB-INF")).getParentFile();
if (logger.isInfoEnabled()) {
logger.info("SuggestCreator: \nDirectory=" + baseDir + "\nOptions=" + suggestCreatorCmdList);
logger.info("SuggestCreator: \nDirectory=" + baseDir + "\nOptions=" + cmdList);
}
final ProcessBuilder pb = new ProcessBuilder(suggestCreatorCmdList);
final ProcessBuilder pb = new ProcessBuilder(cmdList);
pb.directory(baseDir);
pb.redirectErrorStream(true);

View file

@ -1,43 +0,0 @@
/*
* Copyright 2012-2015 CodeLibs Project and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.codelibs.fess.job;
import org.codelibs.fess.helper.HotSearchWordHelper;
import org.codelibs.fess.util.ComponentUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UpdateHotWordJob {
private static final Logger logger = LoggerFactory.getLogger(UpdateHotWordJob.class);
public String execute() {
final HotSearchWordHelper hotSearchWordHelper = ComponentUtil.getHotSearchWordHelper();
final StringBuilder resultBuf = new StringBuilder();
// hot words
try {
hotSearchWordHelper.reload();
} catch (final Exception e) {
logger.error("Failed to store a search log.", e);
resultBuf.append(e.getMessage()).append("\n");
}
return resultBuf.toString();
}
}

View file

@ -555,7 +555,7 @@ public class FessLabels extends ActionMessages {
public static final String LABELS_search_title = "{labels.search_title}";
/** The key of the message: Popular Words: */
public static final String LABELS_search_hot_search_word = "{labels.search_hot_search_word}";
public static final String LABELS_search_popular_word_word = "{labels.search_popular_word_word}";
/** The key of the message: -- Sort -- */
public static final String LABELS_search_result_select_sort = "{labels.search_result_select_sort}";
@ -927,7 +927,7 @@ public class FessLabels extends ActionMessages {
public static final String LABELS_failure_count_threshold = "{labels.failure_count_threshold}";
/** The key of the message: Popular Word Response */
public static final String LABELS_hot_search_word_enabled = "{labels.hot_search_word_enabled}";
public static final String LABELS_popular_word_word_enabled = "{labels.popular_word_word_enabled}";
/** The key of the message: Web */
public static final String LABELS_supported_search_web = "{labels.supported_search_web}";

View file

@ -40,6 +40,12 @@ public interface FessConfig extends FessEnv {
/** The key of the configuration. e.g. sha256 */
String APP_DIGEST_ALGORISM = "app.digest.algorism";
/** The key of the configuration. e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC */
String JVM_CRAWLER_OPTIONS = "jvm.crawler.options";
/** The key of the configuration. e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC */
String JVM_SUGGEST_OPTIONS = "jvm.suggest.options";
/** The key of the configuration. e.g. false */
String CRAWLER_DOCUMENT_CACHE_ENABLE = "crawler.document.cache.enable";
@ -307,6 +313,39 @@ public interface FessConfig extends FessEnv {
/** The key of the configuration. e.g. crawlinginfo */
String ONLINE_HELP_NAME_CRAWLINGINFO = "online.help.name.crawlinginfo";
/** The key of the configuration. e.g. 0 */
String SUGGEST_POPULAR_WORD_SEED = "suggest.popular.word.seed";
/** The key of the configuration. e.g. 10 */
String SUGGEST_POPULAR_WORD_SIZE = "suggest.popular.word.size";
/** The key of the configuration. e.g. 30 */
String SUGGEST_POPULAR_WORD_WINDOW_SIZE = "suggest.popular.word.window.size";
/** The key of the configuration. e.g. 1 */
String SUGGEST_MIN_HIT_COUNT = "suggest.min.hit.count";
/** The key of the configuration. e.g. _default */
String SUGGEST_FIELD_CONTENTS = "suggest.field.contents";
/** The key of the configuration. e.g. label */
String SUGGEST_FIELD_TAGS = "suggest.field.tags";
/** The key of the configuration. e.g. role */
String SUGGEST_FIELD_ROLES = "suggest.field.roles";
/** The key of the configuration. e.g. content,title */
String SUGGEST_FIELD_INDEX_CONTENTS = "suggest.field.index.contents";
/** The key of the configuration. e.g. 1 */
String SUGGEST_UPDATE_REQUEST_INTERVAL = "suggest.update.request.interval";
/** The key of the configuration. e.g. 1 */
String SUGGEST_SOURCE_READER_SCROLL_SIZE = "suggest.source.reader.scroll.size";
/** The key of the configuration. e.g. guest */
String SUGGEST_ROLE_FILTERS = "suggest.role.filters";
/**
* Get the value of property as {@link String}.
* @param propertyKey The key of the property. (NotNull)
@ -368,6 +407,21 @@ public interface FessConfig extends FessEnv {
*/
String getAppDigestAlgorism();
/**
* Get the value for the key 'jvm.crawler.options'. <br>
* The value is, e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC <br>
* comment: JVM options
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getJvmCrawlerOptions();
/**
* Get the value for the key 'jvm.suggest.options'. <br>
* The value is, e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getJvmSuggestOptions();
/**
* Get the value for the key 'crawler.document.cache.enable'. <br>
* The value is, e.g. false <br>
@ -1183,6 +1237,133 @@ public interface FessConfig extends FessEnv {
*/
String getOnlineHelpNameCrawlinginfo();
/**
* Get the value for the key 'suggest.popular.word.seed'. <br>
* The value is, e.g. 0 <br>
* comment: ------
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestPopularWordSeed();
/**
* Get the value for the key 'suggest.popular.word.seed' as {@link Integer}. <br>
* The value is, e.g. 0 <br>
* comment: ------
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestPopularWordSeedAsInteger();
/**
* Get the value for the key 'suggest.popular.word.size'. <br>
* The value is, e.g. 10 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestPopularWordSize();
/**
* Get the value for the key 'suggest.popular.word.size' as {@link Integer}. <br>
* The value is, e.g. 10 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestPopularWordSizeAsInteger();
/**
* Get the value for the key 'suggest.popular.word.window.size'. <br>
* The value is, e.g. 30 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestPopularWordWindowSize();
/**
* Get the value for the key 'suggest.popular.word.window.size' as {@link Integer}. <br>
* The value is, e.g. 30 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestPopularWordWindowSizeAsInteger();
/**
* Get the value for the key 'suggest.min.hit.count'. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestMinHitCount();
/**
* Get the value for the key 'suggest.min.hit.count' as {@link Integer}. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestMinHitCountAsInteger();
/**
* Get the value for the key 'suggest.field.contents'. <br>
* The value is, e.g. _default <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestFieldContents();
/**
* Get the value for the key 'suggest.field.tags'. <br>
* The value is, e.g. label <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestFieldTags();
/**
* Get the value for the key 'suggest.field.roles'. <br>
* The value is, e.g. role <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestFieldRoles();
/**
* Get the value for the key 'suggest.field.index.contents'. <br>
* The value is, e.g. content,title <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestFieldIndexContents();
/**
* Get the value for the key 'suggest.update.request.interval'. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestUpdateRequestInterval();
/**
* Get the value for the key 'suggest.update.request.interval' as {@link Integer}. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestUpdateRequestIntervalAsInteger();
/**
* Get the value for the key 'suggest.source.reader.scroll.size'. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestSourceReaderScrollSize();
/**
* Get the value for the key 'suggest.source.reader.scroll.size' as {@link Integer}. <br>
* The value is, e.g. 1 <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
* @throws NumberFormatException When the property is not integer.
*/
Integer getSuggestSourceReaderScrollSizeAsInteger();
/**
* Get the value for the key 'suggest.role.filters'. <br>
* The value is, e.g. guest <br>
* @return The value of found property. (NotNull: if not found, exception but basically no way)
*/
String getSuggestRoleFilters();
/**
* The simple implementation for configuration.
* @author FreeGen
@ -1216,6 +1397,14 @@ public interface FessConfig extends FessEnv {
return get(FessConfig.APP_DIGEST_ALGORISM);
}
public String getJvmCrawlerOptions() {
return get(FessConfig.JVM_CRAWLER_OPTIONS);
}
public String getJvmSuggestOptions() {
return get(FessConfig.JVM_SUGGEST_OPTIONS);
}
public String getCrawlerDocumentCacheEnable() {
return get(FessConfig.CRAWLER_DOCUMENT_CACHE_ENABLE);
}
@ -1655,5 +1844,73 @@ public interface FessConfig extends FessEnv {
public String getOnlineHelpNameCrawlinginfo() {
return get(FessConfig.ONLINE_HELP_NAME_CRAWLINGINFO);
}
public String getSuggestPopularWordSeed() {
return get(FessConfig.SUGGEST_POPULAR_WORD_SEED);
}
public Integer getSuggestPopularWordSeedAsInteger() {
return getAsInteger(FessConfig.SUGGEST_POPULAR_WORD_SEED);
}
public String getSuggestPopularWordSize() {
return get(FessConfig.SUGGEST_POPULAR_WORD_SIZE);
}
public Integer getSuggestPopularWordSizeAsInteger() {
return getAsInteger(FessConfig.SUGGEST_POPULAR_WORD_SIZE);
}
public String getSuggestPopularWordWindowSize() {
return get(FessConfig.SUGGEST_POPULAR_WORD_WINDOW_SIZE);
}
public Integer getSuggestPopularWordWindowSizeAsInteger() {
return getAsInteger(FessConfig.SUGGEST_POPULAR_WORD_WINDOW_SIZE);
}
public String getSuggestMinHitCount() {
return get(FessConfig.SUGGEST_MIN_HIT_COUNT);
}
public Integer getSuggestMinHitCountAsInteger() {
return getAsInteger(FessConfig.SUGGEST_MIN_HIT_COUNT);
}
public String getSuggestFieldContents() {
return get(FessConfig.SUGGEST_FIELD_CONTENTS);
}
public String getSuggestFieldTags() {
return get(FessConfig.SUGGEST_FIELD_TAGS);
}
public String getSuggestFieldRoles() {
return get(FessConfig.SUGGEST_FIELD_ROLES);
}
public String getSuggestFieldIndexContents() {
return get(FessConfig.SUGGEST_FIELD_INDEX_CONTENTS);
}
public String getSuggestUpdateRequestInterval() {
return get(FessConfig.SUGGEST_UPDATE_REQUEST_INTERVAL);
}
public Integer getSuggestUpdateRequestIntervalAsInteger() {
return getAsInteger(FessConfig.SUGGEST_UPDATE_REQUEST_INTERVAL);
}
public String getSuggestSourceReaderScrollSize() {
return get(FessConfig.SUGGEST_SOURCE_READER_SCROLL_SIZE);
}
public Integer getSuggestSourceReaderScrollSizeAsInteger() {
return getAsInteger(FessConfig.SUGGEST_SOURCE_READER_SCROLL_SIZE);
}
public String getSuggestRoleFilters() {
return get(FessConfig.SUGGEST_ROLE_FILTERS);
}
}
}

View file

@ -21,7 +21,6 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
@ -31,11 +30,8 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringEscapeUtils;
import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.fess.Constants;
import org.codelibs.fess.entity.FacetQueryView;
import org.codelibs.fess.helper.HotSearchWordHelper;
import org.codelibs.fess.helper.HotSearchWordHelper.Range;
import org.codelibs.fess.helper.ViewHelper;
import org.codelibs.fess.util.ComponentUtil;
import org.lastaflute.di.util.LdiURLUtil;
@ -72,64 +68,6 @@ public class FessFunctions {
return value;
}
public static List<String> hsw(final String value, final Integer size) {
if (!isSupportHotSearchWord()) {
return Collections.emptyList();
}
Range range;
if (value == null) {
range = Range.ENTIRE;
} else if ("day".equals(value) || "1".equals(value)) {
range = Range.ONE_DAY;
} else if ("week".equals(value) || "7".equals(value)) {
range = Range.ONE_DAY;
} else if ("month".equals(value) || "30".equals(value)) {
range = Range.ONE_DAY;
} else if ("year".equals(value) || "365".equals(value)) {
range = Range.ONE_DAY;
} else {
range = Range.ENTIRE;
}
final HotSearchWordHelper hotSearchWordHelper = ComponentUtil.getHotSearchWordHelper();
final List<String> wordList = hotSearchWordHelper.getHotSearchWordList(range);
if (wordList.size() > size) {
return wordList.subList(0, size);
}
return wordList;
}
public static Integer hswsize(final String value) {
if (!isSupportHotSearchWord()) {
return 0;
}
Range range;
if (value == null) {
range = Range.ENTIRE;
} else if ("day".equals(value) || "1".equals(value)) {
range = Range.ONE_DAY;
} else if ("week".equals(value) || "7".equals(value)) {
range = Range.ONE_DAY;
} else if ("month".equals(value) || "30".equals(value)) {
range = Range.ONE_DAY;
} else if ("year".equals(value) || "365".equals(value)) {
range = Range.ONE_DAY;
} else {
range = Range.ENTIRE;
}
final HotSearchWordHelper hotSearchWordHelper = ComponentUtil.getHotSearchWordHelper();
return hotSearchWordHelper.getHotSearchWordList(range).size();
}
private static boolean isSupportHotSearchWord() {
final DynamicProperties crawlerProperties = ComponentUtil.getCrawlerProperties();
return crawlerProperties != null
&& Constants.TRUE.equals(crawlerProperties.getProperty(Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY, Constants.TRUE));
}
public static Date date(final Long value) {
if (value == null) {
return null;

View file

@ -29,14 +29,15 @@ import org.codelibs.fess.helper.CrawlingConfigHelper;
import org.codelibs.fess.helper.CrawlingInfoHelper;
import org.codelibs.fess.helper.DuplicateHostHelper;
import org.codelibs.fess.helper.FileTypeHelper;
import org.codelibs.fess.helper.HotSearchWordHelper;
import org.codelibs.fess.helper.IndexingHelper;
import org.codelibs.fess.helper.IntervalControlHelper;
import org.codelibs.fess.helper.JobHelper;
import org.codelibs.fess.helper.KeyMatchHelper;
import org.codelibs.fess.helper.LabelTypeHelper;
import org.codelibs.fess.helper.PathMappingHelper;
import org.codelibs.fess.helper.PopularWordHelper;
import org.codelibs.fess.helper.QueryHelper;
import org.codelibs.fess.helper.RoleQueryHelper;
import org.codelibs.fess.helper.SambaHelper;
import org.codelibs.fess.helper.SearchLogHelper;
import org.codelibs.fess.helper.SuggestHelper;
@ -52,6 +53,10 @@ import org.lastaflute.di.core.SingletonLaContainer;
import org.lastaflute.di.core.factory.SingletonLaContainerFactory;
public final class ComponentUtil {
private static final String ROLE_QUERY_HELPER = "roleQueryHelper";
private static final String SUGGEST_HELPER = "suggestHelper";
private static final String FESS_ES_CLIENT = "fessEsClient";
private static final String DICTIONARY_MANAGER = "dictionaryManager";
@ -84,7 +89,7 @@ public final class ComponentUtil {
private static final String PATH_MAPPING_HELPER = "pathMappingHelper";
private static final String HOT_SEARCH_WORD_HELPER = "hotSearchWordHelper";
private static final String POPULAR_WORD_HELPER = "popularWordHelper";
private static final String CRAWLING_INFO_HELPER = "crawlingInfoHelper";
@ -169,8 +174,8 @@ public final class ComponentUtil {
return SingletonLaContainer.getComponent(CRAWLING_INFO_HELPER);
}
public static HotSearchWordHelper getHotSearchWordHelper() {
return SingletonLaContainer.getComponent(HOT_SEARCH_WORD_HELPER);
public static PopularWordHelper getPopularWordHelper() {
return SingletonLaContainer.getComponent(POPULAR_WORD_HELPER);
}
public static PathMappingHelper getPathMappingHelper() {
@ -265,11 +270,15 @@ public final class ComponentUtil {
return SingletonLaContainer.getComponent(clazz);
}
public static SuggestHelper getSuggestHelper() {
return SingletonLaContainer.getComponent(SUGGEST_HELPER);
}
public static RoleQueryHelper getRoleQueryHelper() {
return SingletonLaContainer.getComponent(ROLE_QUERY_HELPER);
}
public static boolean hasQueryHelper() {
return SingletonLaContainerFactory.getContainer().hasComponentDef(QUERY_HELPER);
}
public static SuggestHelper getSuggestHelper() {
return getComponent(SuggestHelper.class);
}
}

View file

@ -155,8 +155,7 @@
</component>
<component name="userAgentHelper" class="org.codelibs.fess.helper.UserAgentHelper">
</component>
<component name="hotSearchWordHelper" class="org.codelibs.fess.helper.HotSearchWordHelper">
<property name="excludedWordPattern">java.util.regex.Pattern.compile(".*[a-zA-Z0-9_]+:.*")</property>
<component name="popularWordHelper" class="org.codelibs.fess.helper.PopularWordHelper">
</component>
<component name="userInfoHelper" class="org.codelibs.fess.helper.impl.CookieUserInfoHelperImpl">
</component>

View file

@ -31,25 +31,6 @@
"hi", "hu", "hy", "id", "it", "ja", "lv", "ko", "nl", "no", "pt",
"ro", "ru", "sv", "th", "tr", "zh_CN", "zh_TW", "zh" }</property>
-->
<property name="crawlerJavaOptions">
[
"-Djava.awt.headless=true",
"-server",
"-Xmx256m",
"-XX:MaxMetaspaceSize=128m",
"-XX:CompressedClassSpaceSize=32m",
"-XX:-UseGCOverheadLimit",
"-XX:+UseConcMarkSweepGC",
"-XX:CMSInitiatingOccupancyFraction=75",
"-XX:+UseParNewGC",
"-XX:+UseTLAB",
"-XX:+DisableExplicitGC"
]
</property>
<!-- remote debug
"-Xdebug",
"-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:8000",
-->
<postConstruct name="addAdminRoles">
<arg>["fess"]</arg>
</postConstruct>

View file

@ -17,6 +17,35 @@ app.cipher.algorism=aes
app.cipher.key=__change_me__
app.digest.algorism=sha256
# JVM options
jvm.crawler.options=\
-Djava.awt.headless=true\
-server\
-Xmx256m\
-XX:MaxMetaspaceSize=128m\
-XX:CompressedClassSpaceSize=32m\
-XX:-UseGCOverheadLimit\
-XX:+UseConcMarkSweepGC\
-XX:CMSInitiatingOccupancyFraction=75\
-XX:+UseParNewGC\
-XX:+UseTLAB\
-XX:+DisableExplicitGC
jvm.suggest.options=\
-Djava.awt.headless=true\
-server\
-Xmx256m\
-XX:MaxMetaspaceSize=128m\
-XX:CompressedClassSpaceSize=32m\
-XX:-UseGCOverheadLimit\
-XX:+UseConcMarkSweepGC\
-XX:CMSInitiatingOccupancyFraction=75\
-XX:+UseParNewGC\
-XX:+UseTLAB\
-XX:+DisableExplicitGC
#-Xdebug\
#-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:8000\
# ========================================================================================
# Index
# ====
@ -163,3 +192,20 @@ online.help.name.duplicatehost=duplicatehost
online.help.name.scheduler=scheduler
online.help.name.crawlinginfo=crawlinginfo
# ----------------------------------------------------------
# Suggest
# ------
suggest.popular.word.seed=0
suggest.popular.word.size=10
suggest.popular.word.window.size=30
suggest.min.hit.count=1
suggest.field.contents=_default
suggest.field.tags=label
suggest.field.roles=role
suggest.field.index.contents=content,title
suggest.update.request.interval=1
suggest.source.reader.scroll.size=1
suggest.role.filters=\
guest

View file

@ -4,6 +4,15 @@
"refresh_interval": "1s",
"number_of_shards": 10,
"number_of_replicas": 0
},
"dbflute": {
"search_log": {
"properties": {
"roles": {
"array": true
}
}
}
}
}
}

View file

@ -11,6 +11,10 @@
"type": "string",
"index": "not_analyzed"
},
"roles": {
"type": "string",
"index": "not_analyzed"
},
"queryId": {
"type": "string",
"index": "not_analyzed"

View file

@ -14,8 +14,6 @@
</component>
<component name="aggregateLogJob" class="org.codelibs.fess.job.AggregateLogJob" instance="prototype">
</component>
<component name="updateHotWordJob" class="org.codelibs.fess.job.UpdateHotWordJob" instance="prototype">
</component>
<component name="purgeDocJob" class="org.codelibs.fess.job.PurgeDocJob" instance="prototype">
</component>
<component name="purgeLogJob" class="org.codelibs.fess.job.PurgeLogJob" instance="prototype">

View file

@ -177,7 +177,7 @@ labels.prev_page=Prev
labels.next_page=Next
labels.did_not_match=Your search - <b>{0}</b> - did not match any documents.
labels.search_title=Fess
labels.search_hot_search_word=Popular Words:
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_created_asc=Date (ascending)
@ -304,7 +304,7 @@ labels.append_query_param_enabled=Append Params to URL
labels.supported_search_feature=Supported Search
labels.ignore_failure_type=Excluded Failure Type
labels.failure_count_threshold=Failure Count Threshold
labels.hot_search_word_enabled=Popular Word Response
labels.popular_word_word_enabled=Popular Word Response
labels.supported_search_web=Web
labels.supported_search_none=Not Available
labels.purge_search_log_day=Purge Search Log Before

View file

@ -177,7 +177,7 @@ labels.prev_page=Prev
labels.next_page=Next
labels.did_not_match=Your search - <b>{0}</b> - did not match any documents.
labels.search_title=Fess
labels.search_hot_search_word=Popular Words:
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_created_asc=Date (ascending)
@ -304,7 +304,7 @@ labels.append_query_param_enabled=Append Params to URL
labels.supported_search_feature=Supported Search
labels.ignore_failure_type=Excluded Failure Type
labels.failure_count_threshold=Failure Count Threshold
labels.hot_search_word_enabled=Popular Word Response
labels.popular_word_word_enabled=Popular Word Response
labels.supported_search_web=Web
labels.supported_search_none=Not Available
labels.purge_search_log_day=Purge Search Log Before

View file

@ -176,7 +176,7 @@ labels.prev_page = \u524d\u3078
labels.next_page = \u6b21\u3078
labels.did_not_match = <b>{0}</b> \u306b\u4e00\u81f4\u3059\u308b\u60c5\u5831\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002
labels.search_title = Fess
labels.search_hot_search_word = \u4eba\u6c17\u30ef\u30fc\u30c9:
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_created_asc = \u65e5\u4ed8 (\u6607\u9806)
@ -301,7 +301,7 @@ labels.append_query_param_enabled = \u691c\u7d22\u30d1\u30e9\u30e1\u30fc\u30bf\u
labels.supported_search_feature = \u30b5\u30dd\u30fc\u30c8\u3059\u308b\u691c\u7d22
labels.ignore_failure_type = \u9664\u5916\u3059\u308b\u30a8\u30e9\u30fc\u306e\u7a2e\u985e
labels.failure_count_threshold = \u969c\u5bb3\u6570\u306e\u3057\u304d\u3044\u5024
labels.hot_search_word_enabled = \u4eba\u6c17\u30ef\u30fc\u30c9\u306e\u30ec\u30b9\u30dd\u30f3\u30b9
labels.popular_word_word_enabled = \u4eba\u6c17\u30ef\u30fc\u30c9\u306e\u30ec\u30b9\u30dd\u30f3\u30b9
labels.supported_search_web = \u30a6\u30a7\u30d6
labels.supported_search_none = \u5229\u7528\u4e0d\u53ef
labels.purge_search_log_day = \u4ee5\u524d\u306e\u691c\u7d22\u30ed\u30b0\u3092\u524a\u9664

View file

@ -35,30 +35,6 @@
</example>
</function>
<function>
<description>
Returns a list of hot search words.
</description>
<name>hsw</name>
<function-class>org.codelibs.fess.taglib.FessFunctions</function-class>
<function-signature>java.util.List hsw(java.lang.String, java.lang.Integer)</function-signature>
<example>
${fe:hsw("week", 5)}
</example>
</function>
<function>
<description>
Returns a size of hot search words.
</description>
<name>hswsize</name>
<function-class>org.codelibs.fess.taglib.FessFunctions</function-class>
<function-signature>java.lang.Integer hswsize(java.lang.String)</function-signature>
<example>
${fe:hswsize("week")}
</example>
</function>
<function>
<description>
Returns Date from a given value.

View file

@ -1,27 +1,33 @@
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<la:form action="/search" method="get" styleId="searchForm" styleClass="searchResultForm">
<la:form action="/search" method="get" styleId="searchForm"
styleClass="searchResultForm">
${fe:facetForm()}${fe:geoForm()}
<nav class="navbar navbar-dark bg-inverse navbar-static-top pos-f-t">
<la:link styleClass="navbar-brand" href="/">
<img src="${f:url('/images/logo-head.png')}" alt="<la:message key="labels.header_brand_name" />" />
<img src="${f:url('/images/logo-head.png')}"
alt="<la:message key="labels.header_brand_name" />" />
</la:link>
<div class="form-inline navbar-form pull-right">
<la:text property="query" maxlength="1000" styleId="query" styleClass="form-control" autocomplete="off"/>
<button class="btn medium btn-primary" type="submit" name="search" id="searchButton">
<i class="icon-search icon-white"></i><span class="hidden-phone"><la:message key="labels.search" /></span>
<la:text property="q" maxlength="1000" styleId="query"
styleClass="form-control" autocomplete="off" />
<button class="btn medium btn-primary" type="submit" name="search"
id="searchButton">
<i class="icon-search icon-white"></i><span class="hidden-phone"><la:message
key="labels.search" /></span>
</button>
<a href="#searchOptions" role="button" class="btn btn-secondary" data-toggle="modal"><i class="icon-cog"></i><span
class="hidden-phone"
><la:message key="labels.header_form_option_btn" /></span></a>
<a href="#searchOptions" role="button" class="btn btn-secondary"
data-toggle="modal"><i class="icon-cog"></i><span
class="hidden-phone"><la:message
key="labels.header_form_option_btn" /></span></a>
</div>
</nav>
<div class="modal fade" id="searchOptions" tabindex="-1" role="dialog" aria-labelledby="searchOptionsLabel"
aria-hidden="true"
>
<div class="modal fade" id="searchOptions" tabindex="-1" role="dialog"
aria-labelledby="searchOptionsLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span> <span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="searchOptionsLabel">
@ -31,7 +37,8 @@ ${fe:facetForm()}${fe:geoForm()}
<div class="modal-body">
<fieldset class="form-group">
<label for="contentNum"><la:message key="labels.index_num" /></label>
<la:select property="num" styleId="numSearchOption" styleClass="form-control" style="display:block;">
<la:select property="num" styleId="numSearchOption"
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_num" />
</option>
@ -44,8 +51,10 @@ ${fe:facetForm()}${fe:geoForm()}
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentSort"><la:message key="labels.index_sort" /></label>
<la:select property="sort" styleId="sortSearchOption" styleClass="form-control" style="display:block;">
<label for="contentSort"><la:message
key="labels.index_sort" /></label>
<la:select property="sort" styleId="sortSearchOption"
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
@ -86,8 +95,10 @@ ${fe:facetForm()}${fe:geoForm()}
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentLang"><la:message key="labels.index_lang" /></label>
<la:select property="lang" styleId="langSearchOption" multiple="true" styleClass="form-control">
<label for="contentLang"><la:message
key="labels.index_lang" /></label>
<la:select property="lang" styleId="langSearchOption"
multiple="true" styleClass="form-control">
<c:forEach var="item" items="${langItems}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
@ -97,12 +108,15 @@ ${fe:facetForm()}${fe:geoForm()}
</fieldset>
<c:if test="${displayLabelTypeItems}">
<fieldset class="form-group">
<label for="contentLabelType"><la:message key="labels.index_label" /></label>
<la:select property="fields.label" styleId="labelTypeSearchOption" multiple="true" styleClass="form-control">
<label for="contentLabelType"><la:message
key="labels.index_label" /></label>
<la:select property="fields.label"
styleId="labelTypeSearchOption" multiple="true"
styleClass="form-control">
<c:forEach var="item" items="${labelTypeItems}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</la:option>
${f:h(item.label)}
</la:option>
</c:forEach>
</la:select>
</fieldset>
@ -112,7 +126,8 @@ ${fe:facetForm()}${fe:geoForm()}
<button class="btn btn-secondary" id="searchOptionsClearButton">
<la:message key="labels.search_options_clear" />
</button>
<button class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">
<button class="btn btn-secondary" data-dismiss="modal"
aria-hidden="true">
<la:message key="labels.search_options_close" />
</button>
<button class="btn btn-primary" type="submit">

View file

@ -23,145 +23,135 @@ ${fe:facetForm()}${fe:geoForm()}
</li>
</c:if>
</ul>
<div class="search-box navbar-form col-lg-5 col-md-6 col-sm-6 col-xs-8 pull-right" role="search">
<div
class="search-box navbar-form col-lg-5 col-md-6 col-sm-6 col-xs-8 pull-right"
role="search">
<div class="input-group">
<la:text property="query" maxlength="1000" styleId="query" styleClass="form-control"
autocomplete="off" />
<div class="input-group-btn">
<la:text property="q" maxlength="1000" styleId="query"
styleClass="form-control" autocomplete="off" />
<span class="input-group-btn">
<button type="submit" name="search" id="searchButton"
class="btn btn-primary">
<i class="fa fa-search"></i> <span class="hidden-sm-down"><la:message
key="labels.search" /></span>
<i class="fa fa-search"></i>
</button>
<button type="button" class="btn btn-primary dropdown-toggle"
id="searchOptionsButton" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="sr-only"><la:message
<button type="button" class="btn btn-default"
data-toggle="control-options" data-target="#searchOptions"
id="searchOptionsButton">
<i class="fa fa-cog"></i> <span class="sr-only"><la:message
key="labels.header_form_option_btn" /></span>
</button>
<div class="dropdown-menu dropdown-menu-right">
<a href="#searchOptions" class="dropdown-item" data-toggle="modal"><la:message
key="labels.header_form_option_btn" /></a>
</div>
</div>
</span>
</div>
</div>
</nav>
<div class="modal fade" id="searchOptions" tabindex="-1" role="dialog"
aria-labelledby="searchOptionsLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span> <span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="searchOptionsLabel">
<la:message key="labels.search_options" />
</h4>
</div>
<div class="modal-body">
<fieldset class="form-group">
<label for="contentNum"><la:message key="labels.index_num" /></label>
<la:select property="num" styleId="numSearchOption"
styleClass="form-control" style="display:block;">
<option value="">
<la:message key="labels.search_result_select_num" />
</option>
<la:option value="10">10</la:option>
<la:option value="20">20</la:option>
<la:option value="30">30</la:option>
<la:option value="40">40</la:option>
<la:option value="50">50</la:option>
<la:option value="100">100</la:option>
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentSort"><la:message
key="labels.index_sort" /></label>
<la:select property="sort" styleId="sortSearchOption"
styleClass="form-control" style="display:block;">
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
<la:option value="created.asc">
<la:message key="labels.search_result_sort_created_asc" />
<div id="searchOptions" class="control-options">
<div class="container">
<h4 id="searchOptionsLabel">
<la:message key="labels.search_options" />
</h4>
<div>
<fieldset class="form-group">
<label for="contentNum"><la:message key="labels.index_num" /></label>
<la:select property="num" styleId="numSearchOption"
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_num" />
</option>
<la:option value="10">10</la:option>
<la:option value="20">20</la:option>
<la:option value="30">30</la:option>
<la:option value="40">40</la:option>
<la:option value="50">50</la:option>
<la:option value="100">100</la:option>
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentSort"><la:message
key="labels.index_sort" /></label>
<la:select property="sort" styleId="sortSearchOption"
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
<la:option value="created.asc">
<la:message key="labels.search_result_sort_created_asc" />
</la:option>
<la:option value="created.desc">
<la:message key="labels.search_result_sort_created_desc" />
</la:option>
<la:option value="content_length.asc">
<la:message key="labels.search_result_sort_content_length_asc" />
</la:option>
<la:option value="content_length.desc">
<la:message key="labels.search_result_sort_content_length_desc" />
</la:option>
<la:option value="last_modified.asc">
<la:message key="labels.search_result_sort_last_modified_asc" />
</la:option>
<la:option value="last_modified.desc">
<la:message key="labels.search_result_sort_last_modified_desc" />
</la:option>
<c:if test="${searchLogSupport}">
<la:option value="click_count.asc">
<la:message key="labels.search_result_sort_click_count_asc" />
</la:option>
<la:option value="created.desc">
<la:message key="labels.search_result_sort_created_desc" />
<la:option value="click_count.desc">
<la:message key="labels.search_result_sort_click_count_desc" />
</la:option>
<la:option value="content_length.asc">
<la:message key="labels.search_result_sort_content_length_asc" />
</c:if>
<c:if test="${favoriteSupport}">
<la:option value="favorite_count.asc">
<la:message key="labels.search_result_sort_favorite_count_asc" />
</la:option>
<la:option value="content_length.desc">
<la:message key="labels.search_result_sort_content_length_desc" />
<la:option value="favorite_count.desc">
<la:message key="labels.search_result_sort_favorite_count_desc" />
</la:option>
<la:option value="last_modified.asc">
<la:message key="labels.search_result_sort_last_modified_asc" />
</la:option>
<la:option value="last_modified.desc">
<la:message key="labels.search_result_sort_last_modified_desc" />
</la:option>
<c:if test="${searchLogSupport}">
<la:option value="click_count.asc">
<la:message key="labels.search_result_sort_click_count_asc" />
</la:option>
<la:option value="click_count.desc">
<la:message key="labels.search_result_sort_click_count_desc" />
</la:option>
</c:if>
<c:if test="${favoriteSupport}">
<la:option value="favorite_count.asc">
<la:message key="labels.search_result_sort_favorite_count_asc" />
</la:option>
<la:option value="favorite_count.desc">
<la:message key="labels.search_result_sort_favorite_count_desc" />
</la:option>
</c:if>
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentLang"><la:message
key="labels.index_lang" /></label>
<la:select property="lang" styleId="langSearchOption"
multiple="true" styleClass="form-control">
<c:forEach var="item" items="${langItems}">
<la:option value="${f:u(item.value)}">
</c:if>
</la:select>
</fieldset>
<fieldset class="form-group">
<label for="contentLang"><la:message
key="labels.index_lang" /></label>
<la:select property="lang" styleId="langSearchOption"
multiple="true" styleClass="form-control">
<c:forEach var="item" items="${langItems}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</la:option>
</c:forEach>
</la:select>
</fieldset>
<c:if test="${displayLabelTypeItems}">
<fieldset class="form-group">
<label for="contentLabelType"><la:message
key="labels.index_label" /></label>
<la:select property="fields.label" styleId="labelTypeSearchOption"
multiple="true" styleClass="form-control">
<c:forEach var="item" items="${labelTypeItems}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</la:option>
</c:forEach>
</la:select>
</fieldset>
<c:if test="${displayLabelTypeItems}">
<fieldset class="form-group">
<label for="contentLabelType"><la:message
key="labels.index_label" /></label>
<la:select property="fields.label"
styleId="labelTypeSearchOption" multiple="true"
styleClass="form-control">
<c:forEach var="item" items="${labelTypeItems}">
<la:option value="${f:u(item.value)}">
${f:h(item.label)}
</la:option>
</c:forEach>
</la:select>
</fieldset>
</c:if>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="searchOptionsClearButton">
<la:message key="labels.search_options_clear" />
</button>
<button class="btn btn-secondary" data-dismiss="modal"
aria-hidden="true">
<la:message key="labels.search_options_close" />
</button>
<button class="btn btn-primary" type="submit">
<la:message key="labels.search" />
</button>
</div>
</c:if>
</div>
<div>
<button class="btn btn-secondary" id="searchOptionsClearButton">
<la:message key="labels.search_options_clear" />
</button>
<button class="btn btn-primary" type="submit">
<i class="fa fa-search"></i>
<la:message key="labels.search" />
</button>
<button class="btn btn-secondary pull-right"
data-toggle="control-options" data-target="#searchOptions"
id="searchOptionsCloseButton">
<i class="fa fa-angle-double-right"></i>
<la:message key="labels.search_options_close" />
</button>
</div>
</div>
</div>
<!-- /.modal -->
<!-- /#searchOptions -->
</la:form>

View file

@ -1,21 +1,22 @@
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<head profile="http://a9.com/-/spec/opensearch/1.1/">
<meta charset="utf-8">
<meta http-equiv="content-style-type" content="text/css" />
<meta http-equiv="content-script-type" content="text/javascript" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title><la:message key="labels.search_title" /></title>
<link href="${f:url('/css/style-base.css')}" rel="stylesheet"
type="text/css" />
<link href="${f:url('/css/style.css')}" rel="stylesheet" type="text/css" />
<link href="${f:url('/css/font-awesome.min.css')}"
rel="stylesheet" type="text/css" />
</head>
<body>
<body class="help">
<jsp:include page="header.jsp" />
<div class="container">
<div class="row">
<div class="span10">
<div class="col-md-12">
<jsp:include page="${helpPage}" />
@ -26,7 +27,7 @@
</p>
<jsp:include page="footer.jsp" />
</div>
<input type="hidden" id="contextPath" value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${contextPath}" />
<script type="text/javascript"
src="${f:url('/js/jquery-2.1.4.min.js')}"></script>
<script type="text/javascript" src="${f:url('/js/bootstrap.js')}"></script>

View file

@ -14,7 +14,7 @@
<link href="${f:url('/css/style-base.css')}" rel="stylesheet"
type="text/css" />
<link href="${f:url('/css/style.css')}" rel="stylesheet" type="text/css" />
<link href="${f:url('/css/admin/font-awesome.min.css')}"
<link href="${f:url('/css/font-awesome.min.css')}"
rel="stylesheet" type="text/css" />
</head>
<body>
@ -66,17 +66,17 @@
<div class="clearfix">
<div class="input">
<la:text styleClass="query form-control center-block"
property="query" size="50" maxlength="1000"
property="q" size="50" maxlength="1000"
styleId="contentQuery" autocomplete="off" />
</div>
</div>
<c:if test="${fe:hswsize(null) != 0}">
<c:if test="${!empty popularWords}">
<div>
<p class="hotSearchWordBody ellipsis">
<la:message key="labels.search_hot_search_word" />
<c:forEach var="item" items="${fe:hsw(null, 5)}">
<la:message key="labels.search_popular_word_word" />
<c:forEach var="item" items="${popularWords}">
<la:link
href="/search/search?query=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
href="/search/search?q=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
</c:forEach>
</p>
</div>
@ -113,7 +113,7 @@
<label for="contentNum"><la:message
key="labels.index_num" /></label>
<la:select property="num" styleId="numSearchOption"
styleClass="form-control" style="display:block;">
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_num" />
</option>
@ -129,7 +129,7 @@
<label for="contentSort"><la:message
key="labels.index_sort" /></label>
<la:select property="sort" styleId="sortSearchOption"
styleClass="form-control" style="display:block;">
styleClass="form-control">
<option value="">
<la:message key="labels.search_result_select_sort" />
</option>
@ -218,8 +218,7 @@
</div>
<jsp:include page="footer.jsp" />
</div>
<input type="hidden" id="contextPath"
value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${contextPath}" />
<script type="text/javascript"
src="${f:url('/js/jquery-2.1.4.min.js')}"></script>
<script type="text/javascript" src="${f:url('/js/bootstrap.js')}"></script>

View file

@ -15,10 +15,10 @@
<link href="${f:url('/css/style-base.css')}" rel="stylesheet"
type="text/css" />
<link href="${f:url('/css/style.css')}" rel="stylesheet" type="text/css" />
<link href="${f:url('/css/admin/font-awesome.min.css')}"
<link href="${f:url('/css/font-awesome.min.css')}"
rel="stylesheet" type="text/css" />
</head>
<body>
<body class="search">
<jsp:include page="header.jsp" />
<div class="container">
<div class="row">
@ -26,7 +26,7 @@
<ul class="searchOptionLabels">
<li><la:message key="labels.searchoptions_menu_sort" /> <a
href="#searchOptions" class="label label-primary"
data-toggle="modal"> <c:if test="${empty sort}">
data-toggle="control-options"> <c:if test="${empty sort}">
<la:message key="labels.searchoptions_score" />
</c:if> <c:if test="${sort=='created.asc'}">
<la:message key="labels.search_result_sort_created_asc" />
@ -52,12 +52,12 @@
</a></li>
<li><la:message key="labels.searchoptions_menu_num" /> <a
href="#searchOptions" class="label label-primary"
data-toggle="modal"> <la:message
data-toggle="control-options"> <la:message
key="labels.searchoptions_num" arg0="${f:h(num)}" />
</a></li>
<li><la:message key="labels.searchoptions_menu_lang" /> <a
href="#searchOptions" class="label label-primary"
data-toggle="modal"> <c:if test="${empty lang}">
data-toggle="control-options"> <c:if test="${empty lang}">
<la:message key="labels.searchoptions_all" />
</c:if> <c:if test="${!empty lang}">
<c:forEach var="sLang" items="${lang}">
@ -70,7 +70,8 @@
<c:if test="${displayLabelTypeItems}">
<li><la:message key="labels.searchoptions_menu_labels" /> <a
href="#searchOptions" class="label label-primary"
data-toggle="modal"> <c:if test="${empty fields.label}">
data-toggle="control-options"> <c:if
test="${empty fields.label}">
<la:message key="labels.searchoptions_all" />
</c:if> <c:if test="${!empty fields.label}">
<c:forEach var="sLabel" items="${fields.label}">
@ -84,14 +85,14 @@
</ul>
</div>
</div>
<c:if test="${fe:hswsize(null) != 0}">
<c:if test="${!empty popularWords}">
<div class="row">
<div class="col-md-12">
<p class="hotSearchWordBody ellipsis">
<la:message key="labels.search_hot_search_word" />
<c:forEach var="item" items="${fe:hsw(null, 5)}">
<la:message key="labels.search_popular_word_word" />
<c:forEach var="item" items="${popularWords}">
<la:link
href="/search/search?query=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
href="/search/search?q=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
</c:forEach>
</p>
</div>
@ -110,8 +111,7 @@
</c:choose>
<jsp:include page="footer.jsp" />
</div>
<input type="hidden" id="contextPath"
value="<%=request.getContextPath()%>" />
<input type="hidden" id="contextPath" value="${contextPath}" />
<script type="text/javascript"
src="${f:url('/js/jquery-2.1.4.min.js')}"></script>
<script type="text/javascript" src="${f:url('/js/bootstrap.js')}"></script>

View file

@ -40,7 +40,7 @@
key="labels.search_result_cache" /></la:link>
</c:if>
</div>
<div class="more visible-phone">
<div class="more hidden-md-up">
<a href="#result${s.index}"><la:message key="labels.search_result_more" /></a>
</div>
<div class="info">
@ -79,7 +79,7 @@
</c:forEach>
</ol>
</div>
<div class="col-md-4 visible-desktop visible-tablet">
<aside class="col-md-4 hidden-sm-down">
<%-- Side Content --%>
<c:if test="${screenShotSupport}">
<div id="screenshot"></div>
@ -92,7 +92,7 @@
<c:forEach var="countEntry" items="${fieldData.valueCountMap}">
<c:if test="${countEntry.value != 0 && fe:labelexists(countEntry.key)}">
<li class="list-group-item"><la:link
href="/search/search?query=${f:u(query)}&additional=label%3a${f:u(countEntry.key)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}"
href="/search/search?q=${f:u(q)}&ex_q=label%3a${f:u(countEntry.key)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}"
>
${f:h(fe:label(countEntry.key))}
<span class="label label-default label-pill pull-right">${f:h(countEntry.value)}</span>
@ -108,7 +108,7 @@
<c:forEach var="queryEntry" items="${facetQueryView.queryMap}">
<c:if test="${facetResponse.queryCountMap[queryEntry.value] != 0}">
<li class="list-group-item p-l-md"><la:link
href="/search/search?query=${f:u(query)}&additional=${f:u(queryEntry.value)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}"
href="/search/search?q=${f:u(q)}&ex_q=${f:u(queryEntry.value)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}"
>
<la:message key="${queryEntry.key}" />
<span class="label label-default label-pill pull-right">${f:h(facetResponse.queryCountMap[queryEntry.value])}</span>
@ -117,22 +117,22 @@
</c:forEach>
</ul>
</c:forEach>
<c:if test="${!empty additional}">
<c:if test="${!empty ex_q}">
<div class="pull-right">
<la:link href="/search/search?query=${f:u(query)}" styleClass="btn btn-secondary btn-sm">
<la:link href="/search/search?q=${f:u(q)}" styleClass="btn btn-secondary btn-sm">
<la:message key="labels.facet_label_reset" />
</la:link>
</div>
</c:if>
</c:if>
</div>
</aside>
</div>
<div class="row center">
<nav id="subfooter">
<ul class="pagination">
<c:if test="${existPrevPage}">
<li class="prev"><la:link aria-label="Previous"
href="/search/prev?query=${f:u(query)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">
href="/search/prev?q=${f:u(q)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">
<span aria-hidden="true">&laquo;</span>
<span class="sr-only"><la:message key="labels.prev_page" /></span>
</la:link></li>
@ -149,12 +149,12 @@
<c:if test="${pageNumber == currentPageNumber && pageNumber >= currentPageNumber - 2 && pageNumber <= currentPageNumber + 2}">class="active"</c:if>
>
<la:link
href="/search/move?query=${f:u(query)}&pn=${f:u(pageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">${f:h(pageNumber)}</la:link>
href="/search/move?q=${f:u(q)}&pn=${f:u(pageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">${f:h(pageNumber)}</la:link>
</li>
</c:forEach>
<c:if test="${existNextPage}">
<li class="next"><la:link aria-label="Next"
href="/search/next?query=${f:u(query)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">
href="/search/next?q=${f:u(q)}&pn=${f:u(currentPageNumber)}&num=${f:u(pageSize)}${pagingQuery}${fe:facetQuery()}${fe:geoQuery()}">
<span class="sr-only"><la:message key="labels.next_page" /></span>
<span aria-hidden="true">&raquo;</span>
</la:link></li>

View file

@ -69,7 +69,7 @@
</div>
<div class="form-group">
<label for="hotSearchWord" class="col-sm-3 control-label"><la:message
key="labels.hot_search_word_enabled" /></label>
key="labels.popular_word_word_enabled" /></label>
<div class="col-sm-9">
<la:errors property="hotSearchWord" />
<div class="checkbox">

View file

@ -70,11 +70,11 @@
styleId="contentQuery" autocomplete="off" />
</div>
</div>
<c:if test="${fe:hswsize(null) != 0}">
<c:if test="${!empty popularWords}">
<div>
<p class="hotSearchWordBody ellipsis">
<la:message key="labels.search_hot_search_word" />
<c:forEach var="item" items="${fe:hsw(null, 5)}">
<la:message key="labels.search_popular_word_word" />
<c:forEach var="item" items="${popularWords}">
<la:link
href="/search/search?q=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
</c:forEach>

View file

@ -85,12 +85,12 @@
</ul>
</div>
</div>
<c:if test="${fe:hswsize(null) != 0}">
<c:if test="${!empty popularWords}">
<div class="row">
<div class="col-md-12">
<p class="hotSearchWordBody ellipsis">
<la:message key="labels.search_hot_search_word" />
<c:forEach var="item" items="${fe:hsw(null, 5)}">
<la:message key="labels.search_popular_word_word" />
<c:forEach var="item" items="${popularWords}">
<la:link
href="/search/search?q=${f:u(item)}${fe:facetQuery()}${fe:geoQuery()}">${f:h(item)}</la:link>
</c:forEach>