suggest for 9.3.0

This commit is contained in:
yfujita 2014-10-01 04:40:48 +09:00
parent f795e4fa35
commit f65dc32f1a
23 changed files with 342 additions and 670 deletions

View file

@ -163,6 +163,10 @@ public class Constants extends CoreLibConstants {
public static final String USE_BROWSER_LOCALE_FOR_SEARCH_PROPERTY = "search.use.browser.locale";
public static final String SUGGEST_SEARCH_LOG_PROPERTY = "suggest.searchlog";
public static final String PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY = "purge.suggest.searchlog.day";
public static final String AUTH_CIPHER = "authenticationCipher";
public static final String RETURN_PATH = "jp.sf.fess.ReturnPath";
@ -249,7 +253,7 @@ public class Constants extends CoreLibConstants {
public static final String SAMBA = "SAMBA";
public static final String[] RESERVED = { "+", "-", "&&", "||", "!", "(",
")", "{", "}", "[", "]", "^", "~", "*", "?", "\\", ";", ":", "/" };
")", "{", "}", "[", "]", "^", "~", "*", "?", "\\", ";", ":", "/" };
public static final Pattern SOLR_FIELD_RESERVED_PATTERN = Pattern
.compile("([+\\-!\\(\\){}\\[\\]^\"~\\\\:\\p{Zs}]|(&&)|(\\|\\|))"); // "*", "?",

View file

@ -54,8 +54,6 @@ import jp.sf.fess.db.exentity.SearchLog;
import jp.sf.fess.db.exentity.UserInfo;
import jp.sf.fess.entity.FieldAnalysisResponse;
import jp.sf.fess.entity.LoginInfo;
import jp.sf.fess.entity.SpellCheckResponse;
import jp.sf.fess.entity.SuggestResponse;
import jp.sf.fess.form.IndexForm;
import jp.sf.fess.helper.CrawlingConfigHelper;
import jp.sf.fess.helper.DocumentHelper;
@ -64,6 +62,7 @@ import jp.sf.fess.helper.HotSearchWordHelper.Range;
import jp.sf.fess.helper.LabelTypeHelper;
import jp.sf.fess.helper.OpenSearchHelper;
import jp.sf.fess.helper.QueryHelper;
import jp.sf.fess.helper.RoleQueryHelper;
import jp.sf.fess.helper.SearchLogHelper;
import jp.sf.fess.helper.SystemHelper;
import jp.sf.fess.helper.UserInfoHelper;
@ -72,6 +71,9 @@ import jp.sf.fess.screenshot.ScreenShotManager;
import jp.sf.fess.service.FavoriteLogService;
import jp.sf.fess.service.SearchService;
import jp.sf.fess.suggest.Suggester;
import jp.sf.fess.suggest.entity.SpellCheckResponse;
import jp.sf.fess.suggest.entity.SuggestResponse;
import jp.sf.fess.suggest.service.SuggestService;
import jp.sf.fess.util.ComponentUtil;
import jp.sf.fess.util.FacetResponse;
import jp.sf.fess.util.MoreLikeThisResponse;
@ -149,6 +151,9 @@ public class IndexAction {
@Resource
protected QueryHelper queryHelper;
@Resource
protected RoleQueryHelper roleQueryHelper;
@Resource
protected UserInfoHelper userInfoHelper;
@ -161,6 +166,9 @@ public class IndexAction {
@Resource
protected Suggester suggester;
@Resource
protected SuggestService suggestService;
@Resource
protected DynamicProperties crawlerProperties;
@ -623,9 +631,16 @@ public class IndexAction {
}
try {
final SuggestResponse suggestResponse = searchService
final Set<String> roleSet;
if (roleQueryHelper != null) {
roleSet = roleQueryHelper.build();
} else {
roleSet = new HashSet<>();
}
final SuggestResponse suggestResponse = suggestService
.getSuggestResponse(indexForm.query, suggestFieldName,
labelList, num);
labelList, new ArrayList<String>(roleSet), num);
if (!suggestResponse.isEmpty()) {
suggestResultList.add(suggestResponse);
@ -682,9 +697,17 @@ public class IndexAction {
}
try {
final SpellCheckResponse spellCheckResponse = searchService
final Set<String> roleSet;
if (roleQueryHelper != null) {
roleSet = roleQueryHelper.build();
} else {
roleSet = new HashSet<>();
}
final SpellCheckResponse spellCheckResponse = suggestService
.getSpellCheckResponse(indexForm.query,
spellCheckFieldName, labelList, num);
spellCheckFieldName, labelList,
new ArrayList<String>(roleSet), num);
if (!spellCheckResponse.isEmpty()) {
spellCheckResultList.add(spellCheckResponse);

View file

@ -112,6 +112,10 @@ public class CrawlAction implements Serializable {
Constants.DEFAULT_PURGE_BY_BOTS);
crawlForm.notificationTo = crawlerProperties.getProperty(
Constants.NOTIFICATION_TO_PROPERTY, StringUtil.EMPTY);
crawlForm.suggestSearchLog = crawlerProperties.getProperty(
Constants.SUGGEST_SEARCH_LOG_PROPERTY, Constants.TRUE);
crawlForm.purgeSuggestSearchLogDay = crawlerProperties.getProperty(
Constants.PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY, "30");
if (redirect) {
return "index?redirect=true";
} else {
@ -129,74 +133,74 @@ public class CrawlAction implements Serializable {
@Execute(validator = true, input = "index.jsp")
public String update() {
crawlerProperties
.setProperty(
Constants.DIFF_CRAWLING_PROPERTY,
crawlForm.diffCrawling != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.diffCrawling) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.DIFF_CRAWLING_PROPERTY,
crawlForm.diffCrawling != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.diffCrawling) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.USE_ACL_AS_ROLE,
crawlForm.useAclAsRole != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.useAclAsRole) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.USE_ACL_AS_ROLE,
crawlForm.useAclAsRole != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.useAclAsRole) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.SERVER_ROTATION_PROPERTY,
crawlForm.serverRotation != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.serverRotation) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.SERVER_ROTATION_PROPERTY,
crawlForm.serverRotation != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.serverRotation) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties.setProperty(Constants.DAY_FOR_CLEANUP_PROPERTY,
crawlForm.dayForCleanup);
crawlerProperties.setProperty(Constants.CRAWLING_THREAD_COUNT_PROPERTY,
crawlForm.crawlingThreadCount);
crawlerProperties
.setProperty(
Constants.SEARCH_LOG_PROPERTY,
crawlForm.searchLog != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.searchLog) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.SEARCH_LOG_PROPERTY,
crawlForm.searchLog != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.searchLog) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.USER_INFO_PROPERTY,
crawlForm.userInfo != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.userInfo) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.USER_INFO_PROPERTY,
crawlForm.userInfo != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.userInfo) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.USER_FAVORITE_PROPERTY,
crawlForm.userFavorite != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.userFavorite) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.USER_FAVORITE_PROPERTY,
crawlForm.userFavorite != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.userFavorite) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.WEB_API_XML_PROPERTY,
crawlForm.webApiXml != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.webApiXml) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.WEB_API_XML_PROPERTY,
crawlForm.webApiXml != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.webApiXml) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties
.setProperty(
Constants.WEB_API_JSON_PROPERTY,
crawlForm.webApiJson != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.webApiJson) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.WEB_API_JSON_PROPERTY,
crawlForm.webApiJson != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.webApiJson) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties.setProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY,
crawlForm.defaultLabelValue);
crawlerProperties
.setProperty(
Constants.APPEND_QUERY_PARAMETER_PROPERTY,
crawlForm.appendQueryParameter != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.appendQueryParameter) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.APPEND_QUERY_PARAMETER_PROPERTY,
crawlForm.appendQueryParameter != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.appendQueryParameter) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties.setProperty(
Constants.SUPPORTED_SEARCH_FEATURE_PROPERTY,
crawlForm.supportedSearch);
@ -206,12 +210,12 @@ public class CrawlAction implements Serializable {
Constants.FAILURE_COUNT_THRESHOLD_PROPERTY,
crawlForm.failureCountThreshold);
crawlerProperties
.setProperty(
Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY,
crawlForm.hotSearchWord != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.hotSearchWord) ? Constants.TRUE
: Constants.FALSE);
.setProperty(
Constants.WEB_API_HOT_SEARCH_WORD_PROPERTY,
crawlForm.hotSearchWord != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.hotSearchWord) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties.setProperty(Constants.CSV_FILE_ENCODING_PROPERTY,
crawlForm.csvFileEncoding);
crawlerProperties.setProperty(Constants.PURGE_SEARCH_LOG_DAY_PROPERTY,
@ -224,6 +228,16 @@ public class CrawlAction implements Serializable {
crawlForm.purgeByBots);
crawlerProperties.setProperty(Constants.NOTIFICATION_TO_PROPERTY,
crawlForm.notificationTo);
crawlerProperties
.setProperty(
Constants.SUGGEST_SEARCH_LOG_PROPERTY,
crawlForm.suggestSearchLog != null
&& Constants.ON
.equalsIgnoreCase(crawlForm.suggestSearchLog) ? Constants.TRUE
: Constants.FALSE);
crawlerProperties.setProperty(
Constants.PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY,
crawlForm.purgeSuggestSearchLogDay);
try {
crawlerProperties.store();
SAStrutsUtil.addSessionMessage("success.update_crawler_params");

View file

@ -31,6 +31,9 @@ import jp.sf.fess.form.admin.DocumentForm;
import jp.sf.fess.helper.JobHelper;
import jp.sf.fess.helper.SystemHelper;
import jp.sf.fess.helper.WebManagementHelper;
import jp.sf.fess.suggest.SuggestConstants;
import jp.sf.fess.suggest.server.SuggestSolrServer;
import jp.sf.fess.suggest.service.SuggestService;
import jp.sf.fess.util.ComponentUtil;
import org.apache.solr.client.solrj.SolrQuery;
@ -68,9 +71,6 @@ public class DocumentAction implements Serializable {
@Resource
protected SolrGroupManager solrGroupManager;
@Resource
protected SolrGroup suggestSolrGroup;
@Resource
protected WebManagementHelper webManagementHelper;
@ -80,6 +80,11 @@ public class DocumentAction implements Serializable {
@Resource
protected JobHelper jobHelper;
@Resource
protected SuggestService suggestService;
public Map<String, Long> suggestDocumentNums;
public String getHelpLink() {
return systemHelper.getHelpLink("document");
}
@ -124,6 +129,9 @@ public class DocumentAction implements Serializable {
documentForm.serverStatusList.add(map);
}
}
suggestDocumentNums = getSuggestDocumentNum();
// select group status
documentForm.currentServerForSelect = solrProperties
.getProperty(SolrLibConstants.SELECT_GROUP);
@ -174,15 +182,6 @@ public class DocumentAction implements Serializable {
throw new SSCActionMessagesException(
"errors.failed_to_commit_solr_index");
} else {
final boolean isUpdateSolrGroup;
final SolrGroup updateSolrGroup = solrGroupManager
.getSolrGroup(QueryType.ADD);
if (updateSolrGroup.getGroupName().equals(solrGroup.getGroupName())) {
isUpdateSolrGroup = true;
} else {
isUpdateSolrGroup = false;
}
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
@ -190,18 +189,9 @@ public class DocumentAction implements Serializable {
final long execTime = System.currentTimeMillis();
try {
systemHelper.updateStatus(solrGroup, QueryType.ADD);
if (isUpdateSolrGroup) {
systemHelper.updateStatus(suggestSolrGroup,
QueryType.ADD);
}
solrGroup.commit(true, true, false, true);
systemHelper.updateStatus(solrGroup,
QueryType.COMMIT);
if (isUpdateSolrGroup) {
systemHelper.updateStatus(suggestSolrGroup,
QueryType.COMMIT);
}
if (logger.isInfoEnabled()) {
logger.info("[EXEC TIME] index commit time: "
+ (System.currentTimeMillis() - execTime)
@ -237,15 +227,6 @@ public class DocumentAction implements Serializable {
throw new SSCActionMessagesException(
"errors.failed_to_optimize_solr_index");
} else {
final boolean isUpdateSolrGroup;
final SolrGroup updateSolrGroup = solrGroupManager
.getSolrGroup(QueryType.ADD);
if (updateSolrGroup.getGroupName().equals(solrGroup.getGroupName())) {
isUpdateSolrGroup = true;
} else {
isUpdateSolrGroup = false;
}
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
@ -253,17 +234,9 @@ public class DocumentAction implements Serializable {
final long execTime = System.currentTimeMillis();
try {
systemHelper.updateStatus(solrGroup, QueryType.ADD);
if (isUpdateSolrGroup) {
systemHelper.updateStatus(suggestSolrGroup,
QueryType.ADD);
}
solrGroup.optimize();
systemHelper.updateStatus(solrGroup,
QueryType.OPTIMIZE);
if (isUpdateSolrGroup) {
systemHelper.updateStatus(suggestSolrGroup,
QueryType.OPTIMIZE);
}
if (logger.isInfoEnabled()) {
logger.info("[EXEC TIME] index optimize time: "
+ (System.currentTimeMillis() - execTime)
@ -425,6 +398,59 @@ public class DocumentAction implements Serializable {
return jobHelper.getRunningSessionIdSet();
}
protected Map<String, Long> getSuggestDocumentNum() {
final Map<String, Long> map = new HashMap<String, Long>();
map.put("content", suggestService.getContentDocumentNum());
map.put("searchLog", suggestService.getSearchLogDocumentNum());
map.put("all", map.get("content") + map.get("searchLog"));
return map;
}
@Token(save = false, validate = true)
@Execute(validator = true, input = "index")
public String deleteSuggest() {
final SuggestSolrServer suggestSolrServer = suggestService
.getSuggestSolrServer();
final String query;
if ("content".equals(documentForm.deleteSuggestType)) {
query = "*:* NOT " + SuggestConstants.SuggestFieldNames.SEGMENT
+ ":0";
} else if ("searchLog".equals(documentForm.deleteSuggestType)) {
query = SuggestConstants.SuggestFieldNames.SEGMENT + ":0";
} else {
query = "*:*";
}
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
if (!jobHelper.isCrawlProcessRunning()) {
final long execTime = System.currentTimeMillis();
try {
suggestSolrServer.deleteByQuery(query);
suggestSolrServer.commit();
if (logger.isInfoEnabled()) {
logger.info("[EXEC TIME] suggest index cleanup time: "
+ (System.currentTimeMillis() - execTime)
+ "ms");
}
} catch (final Exception e) {
logger.error("Failed to delete suggest index (query="
+ query + ").", e);
}
} else {
if (logger.isInfoEnabled()) {
logger.info("could not start index cleanup process"
+ " because of running solr process.");
}
}
}
});
thread.start();
SAStrutsUtil.addSessionMessage("success.delete_solr_index");
return showIndex(true);
}
private static class SessionIdList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;

View file

@ -70,9 +70,6 @@ public class SystemAction implements Serializable {
@Resource
protected SolrGroupManager solrGroupManager;
@Resource
protected SolrGroup suggestSolrGroup;
@Resource
protected WebManagementHelper webManagementHelper;
@ -98,23 +95,10 @@ public class SystemAction implements Serializable {
groupPropMap.put(groupName, props);
}
}
final DynamicProperties suggestProps = ComponentUtil
.getSolrGroupProperties(suggestSolrGroup.getGroupName());
if (suggestProps != null) {
groupPropMap.put(suggestSolrGroup.getGroupName(), suggestProps);
}
final String[] serverNames = solrGroupManager.getSolrServerNames();
final String[] suggestServerNames = suggestSolrGroup.getServerNames();
for (int i = 0; i < suggestServerNames.length; i++) {
if (StringUtil.isNotBlank(suggestServerNames[i])) {
suggestServerNames[i] = suggestSolrGroup.getGroupName() + ":"
+ suggestServerNames[i];
}
}
final List<String> serverNameList = new ArrayList<String>();
serverNameList.addAll(Arrays.asList(serverNames));
serverNameList.addAll(Arrays.asList(suggestServerNames));
for (final String name : serverNameList) {
final String[] names = name.split(":");
if (names.length == 2) {
@ -193,11 +177,6 @@ public class SystemAction implements Serializable {
groupPropMap.put(groupName, props);
}
}
final DynamicProperties suggestProps = ComponentUtil
.getSolrGroupProperties(suggestSolrGroup.getGroupName());
if (suggestProps != null) {
groupPropMap.put(suggestSolrGroup.getGroupName(), suggestProps);
}
try {
// server status
@ -257,14 +236,14 @@ public class SystemAction implements Serializable {
}
SAStrutsUtil.addSessionMessage("success.start_crawl_process");
RequestUtil.getRequest().getSession()
.setAttribute(STARTING_CRAWL_PROCESS, Boolean.TRUE);
.setAttribute(STARTING_CRAWL_PROCESS, Boolean.TRUE);
} else {
SAStrutsUtil
.addSessionMessage("success.failed_to_start_crawl_process");
.addSessionMessage("success.failed_to_start_crawl_process");
}
} else {
SAStrutsUtil
.addSessionMessage("success.failed_to_start_crawl_process");
.addSessionMessage("success.failed_to_start_crawl_process");
}
return showIndex(true);
}

View file

@ -38,10 +38,10 @@ import jp.sf.fess.db.allcommon.CDef;
import jp.sf.fess.entity.FieldAnalysisResponse;
import jp.sf.fess.entity.PingResponse;
import jp.sf.fess.entity.PingResponse.Target;
import jp.sf.fess.entity.SpellCheckResponse;
import jp.sf.fess.entity.SuggestResponse;
import jp.sf.fess.entity.SuggestResponse.SuggestResponseList;
import jp.sf.fess.service.SearchService;
import jp.sf.fess.suggest.entity.SpellCheckResponse;
import jp.sf.fess.suggest.entity.SuggestResponse;
import jp.sf.fess.suggest.entity.SuggestResponse.SuggestResponseList;
import jp.sf.fess.util.ComponentUtil;
import jp.sf.fess.util.FacetResponse;
import jp.sf.fess.util.FacetResponse.Field;
@ -113,8 +113,8 @@ public class JsonApiManager extends BaseApiManager implements WebApiManager {
}
}
protected void processPingRequest(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {
protected void processPingRequest(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain) {
final SearchService searchService = ComponentUtil.getSearchService();
int status;
final StringBuilder buf = new StringBuilder(1000);

View file

@ -37,10 +37,10 @@ import jp.sf.fess.db.allcommon.CDef;
import jp.sf.fess.entity.FieldAnalysisResponse;
import jp.sf.fess.entity.PingResponse;
import jp.sf.fess.entity.PingResponse.Target;
import jp.sf.fess.entity.SpellCheckResponse;
import jp.sf.fess.entity.SuggestResponse;
import jp.sf.fess.entity.SuggestResponse.SuggestResponseList;
import jp.sf.fess.service.SearchService;
import jp.sf.fess.suggest.entity.SpellCheckResponse;
import jp.sf.fess.suggest.entity.SuggestResponse;
import jp.sf.fess.suggest.entity.SuggestResponse.SuggestResponseList;
import jp.sf.fess.util.ComponentUtil;
import jp.sf.fess.util.FacetResponse;
import jp.sf.fess.util.FacetResponse.Field;
@ -74,7 +74,7 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
@Override
public void process(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
throws IOException, ServletException {
final String formatType = request.getParameter("type");
switch (getFormatType(formatType)) {
case SEARCH:
@ -102,8 +102,8 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
}
protected void processPingRequest(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {
protected void processPingRequest(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain) {
final SearchService searchService = ComponentUtil.getSearchService();
int status;
final StringBuilder buf = new StringBuilder(1000);
@ -206,7 +206,7 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
if (StringUtil.isNotBlank(name)
&& entry.getValue() != null
&& ComponentUtil.getQueryHelper()
.isApiResponseField(name)) {
.isApiResponseField(name)) {
final String tagName = convertTagName(name);
buf.append('<');
buf.append(tagName);
@ -523,12 +523,12 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
.entrySet()) {
buf.append("<field name=\"")
.append(escapeXml(fEntry.getKey())).append("\">");
.append(escapeXml(fEntry.getKey())).append("\">");
for (final Map.Entry<String, List<Map<String, Object>>> aEntry : fEntry
.getValue().entrySet()) {
buf.append("<analysis name=\"")
.append(escapeXml(aEntry.getKey()))
.append("\">");
.append(escapeXml(aEntry.getKey()))
.append("\">");
for (final Map<String, Object> dataMap : aEntry
.getValue()) {
buf.append("<token>");
@ -538,10 +538,10 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
final Object value = dEntry.getValue();
if (StringUtil.isNotBlank(key) && value != null) {
buf.append("<value name=\"")
.append(escapeXml(key))
.append("\">")
.append(escapeXml(value))
.append("</value>");
.append(escapeXml(key))
.append("\">")
.append(escapeXml(value))
.append("</value>");
}
}
buf.append("</token>");
@ -605,8 +605,8 @@ public class XmlApiManager extends BaseApiManager implements WebApiManager {
for (final Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
buf.append("<name>").append(escapeXml(entry.getKey()))
.append("</name><value>")
.append(escapeXml(entry.getValue())).append("</value>");
.append("</name><value>")
.append(escapeXml(entry.getValue())).append("</value>");
}
buf.append("</data>");
} else if (obj instanceof Date) {

View file

@ -1,10 +0,0 @@
package jp.sf.fess.entity;
import org.apache.solr.client.solrj.response.QueryResponse;
public class SpellCheckResponse extends SuggestResponse {
public SpellCheckResponse(final QueryResponse queryResponse, final int num,
final String query) {
super(queryResponse, num, query);
}
}

View file

@ -1,335 +0,0 @@
/*
* Copyright 2009-2014 the 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 jp.sf.fess.entity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import jp.sf.fess.suggest.SuggestConstants;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
public class SuggestResponse implements Map<String, List<String>> {
protected String searchQuery;
protected long execTime;
private final Map<String, List<String>> parent = new LinkedHashMap<String, List<String>>();
public SuggestResponse(final QueryResponse queryResponse, final int num,
final String query) {
if (queryResponse != null) {
parent.put(query, new SuggestResponseList(queryResponse, query));
setSearchQuery(query);
}
}
public String getSearchQuery() {
return searchQuery;
}
public void setSearchQuery(final String searchQuery) {
this.searchQuery = searchQuery;
}
public long getExecTime() {
return execTime;
}
public void setExecTime(final long execTime) {
this.execTime = execTime;
}
@Override
public int size() {
return parent.size();
}
@Override
public boolean isEmpty() {
return parent.isEmpty();
}
@Override
public boolean containsKey(final Object key) {
return parent.containsKey(key);
}
@Override
public boolean containsValue(final Object value) {
return parent.containsValue(value);
}
@Override
public List<String> get(final Object key) {
return parent.get(key);
}
@Override
public List<String> put(final String key, final List<String> value) {
return parent.put(key, value);
}
@Override
public List<String> remove(final Object key) {
return parent.remove(key);
}
@Override
public void putAll(final Map<? extends String, ? extends List<String>> m) {
parent.putAll(m);
}
@Override
public void clear() {
parent.clear();
}
@Override
public Set<String> keySet() {
return parent.keySet();
}
@Override
public Collection<List<String>> values() {
return parent.values();
}
@Override
public Set<java.util.Map.Entry<String, List<String>>> entrySet() {
return parent.entrySet();
}
public static class SuggestResponseList implements List<String> {
private List<String> parent;
private final List<Integer> frequencies;
private final int frequency;
private final String token;
private final int startOffset;
private final int endOffset;
private final int numFound;
public SuggestResponseList(final QueryResponse queryResponse,
final String query) {
final List<String> valueList = new ArrayList<String>();
final List<Integer> frequencyList = new ArrayList<Integer>();
final SolrDocumentList sdList = queryResponse.getResults();
for (final SolrDocument sd : sdList) {
final Object text = sd
.getFieldValue(SuggestConstants.SuggestFieldNames.TEXT);
final Object freq = sd
.getFieldValue(SuggestConstants.SuggestFieldNames.COUNT);
if (text != null && freq != null) {
valueList.add(text.toString());
frequencyList.add(Integer.parseInt(freq.toString()));
}
}
parent = valueList;
frequencies = frequencyList;
frequency = 1;
token = query;
startOffset = 0;
endOffset = query.length();
numFound = (int) queryResponse.getResults().getNumFound();
}
public SuggestResponseList(final Suggestion suggestion) {
parent = suggestion.getAlternatives();
if (parent == null) {
parent = Collections.emptyList();
}
frequencies = suggestion.getAlternativeFrequencies();
frequency = suggestion.getOriginalFrequency();
token = suggestion.getToken();
startOffset = suggestion.getStartOffset();
endOffset = suggestion.getEndOffset();
numFound = suggestion.getNumFound();
}
public List<Integer> getFrequencies() {
return frequencies;
}
public int getFrequency() {
return frequency;
}
public String getToken() {
return token;
}
public int getStartOffset() {
return startOffset;
}
public int getEndOffset() {
return endOffset;
}
public int getNumFound() {
return numFound;
}
@Override
public int size() {
return parent.size();
}
@Override
public boolean isEmpty() {
return parent.isEmpty();
}
@Override
public boolean contains(final Object o) {
return parent.contains(o);
}
@Override
public Iterator<String> iterator() {
return parent.iterator();
}
@Override
public Object[] toArray() {
return parent.toArray();
}
@Override
public <T> T[] toArray(final T[] a) {
return parent.toArray(a);
}
@Override
public boolean add(final String e) {
return parent.add(e);
}
@Override
public boolean remove(final Object o) {
return parent.remove(o);
}
@Override
public boolean containsAll(final Collection<?> c) {
return parent.containsAll(c);
}
@Override
public boolean addAll(final Collection<? extends String> c) {
return parent.addAll(c);
}
@Override
public boolean addAll(final int index,
final Collection<? extends String> c) {
return parent.addAll(index, c);
}
@Override
public boolean removeAll(final Collection<?> c) {
return parent.removeAll(c);
}
@Override
public boolean retainAll(final Collection<?> c) {
return parent.retainAll(c);
}
@Override
public void clear() {
parent.clear();
}
@Override
public String get(final int index) {
return parent.get(index);
}
@Override
public String set(final int index, final String element) {
return parent.set(index, element);
}
@Override
public void add(final int index, final String element) {
parent.add(index, element);
}
@Override
public String remove(final int index) {
return parent.remove(index);
}
@Override
public int indexOf(final Object o) {
return parent.indexOf(o);
}
@Override
public int lastIndexOf(final Object o) {
return parent.lastIndexOf(o);
}
@Override
public ListIterator<String> listIterator() {
return parent.listIterator();
}
@Override
public ListIterator<String> listIterator(final int index) {
return parent.listIterator(index);
}
@Override
public List<String> subList(final int fromIndex, final int toIndex) {
return parent.subList(fromIndex, toIndex);
}
@Override
public String toString() {
return "SuggestResponseList [parent=" + parent + ", frequencies="
+ frequencies + ", frequency=" + frequency + ", token="
+ token + ", startOffset=" + startOffset + ", endOffset="
+ endOffset + ", numFound=" + numFound + "]";
}
}
@Override
public String toString() {
return "SuggestResponse [searchQuery=" + searchQuery + ", execTime="
+ execTime + ", parent=" + parent + "]";
}
}

View file

@ -94,9 +94,6 @@ public class Crawler implements Serializable {
@Resource
protected SolrGroupManager solrGroupManager;
@Resource
SolrGroup suggestSolrGroup;
@Binding(bindingType = BindingType.MAY)
@Resource
protected ScreenShotManager screenShotManager;
@ -531,13 +528,6 @@ public class Crawler implements Serializable {
statusPolicy.activate(QueryType.OPTIMIZE, serverName);
}
}
final StatusPolicy suggestStatusPolicy = suggestSolrGroup
.getStatusPolicy();
for (final String serverName : suggestSolrGroup.getServerNames()) {
if (suggestStatusPolicy.isActive(QueryType.OPTIMIZE, serverName)) {
suggestStatusPolicy.activate(QueryType.OPTIMIZE, serverName);
}
}
if (logger.isInfoEnabled()) {
logger.info("[EXEC TIME] index optimize time: " + startTime + "ms");
@ -564,13 +554,6 @@ public class Crawler implements Serializable {
statusPolicy.activate(QueryType.COMMIT, serverName);
}
}
final StatusPolicy suggestStatusPolicy = suggestSolrGroup
.getStatusPolicy();
for (final String serverName : suggestSolrGroup.getServerNames()) {
if (suggestStatusPolicy.isActive(QueryType.COMMIT, serverName)) {
suggestStatusPolicy.activate(QueryType.COMMIT, serverName);
}
}
if (logger.isInfoEnabled()) {
logger.info("[EXEC TIME] index commit time: " + startTime + "ms");

View file

@ -85,8 +85,8 @@ public class AdLoginInfoFilter implements Filter {
final String servletPath = ((HttpServletRequest) request)
.getServletPath();
if (redirectLoginError && "/index.do".equals(servletPath)) {
((HttpServletResponse) response)
.sendRedirect("/n2search/error/badRequest");
((HttpServletResponse) response).sendRedirect(httpRequest
.getContextPath() + "error/badRequest");
return;
}
}

View file

@ -95,4 +95,10 @@ public class CrawlForm implements Serializable {
@Maxbytelength(maxbytelength = 1000)
public String notificationTo;
@Maxbytelength(maxbytelength = 10)
public String suggestSearchLog;
@IntRange(min = 0, max = 100000)
public String purgeSuggestSearchLogDay;
}

View file

@ -48,4 +48,7 @@ public class DocumentForm implements Serializable {
@Required(target = "startSolrInstance,stopSolrInstance,reloadSolrInstance")
public String solrInstanceName;
@Required(target = "deleteSuggest")
public String deleteSuggestType;
}

View file

@ -30,6 +30,7 @@ import jp.sf.fess.db.exbhv.pmbean.FavoriteUrlCountPmb;
import jp.sf.fess.db.exentity.ClickLog;
import jp.sf.fess.db.exentity.SearchLog;
import jp.sf.fess.db.exentity.customize.FavoriteUrlCount;
import jp.sf.fess.suggest.service.SuggestService;
import org.codelibs.core.util.DynamicProperties;
import org.codelibs.robot.util.LruHashMap;
@ -52,6 +53,9 @@ public abstract class SearchLogHelper {
protected Map<String, Long> userInfoCache;
@Resource
protected SuggestService suggestService;
@InitMethod
public void init() {
userInfoCache = new LruHashMap<String, Long>(userInfoCacheSize);

View file

@ -30,6 +30,7 @@ import jp.sf.fess.db.exbhv.ClickLogBhv;
import jp.sf.fess.db.exbhv.SearchLogBhv;
import jp.sf.fess.db.exbhv.UserInfoBhv;
import jp.sf.fess.db.exentity.ClickLog;
import jp.sf.fess.db.exentity.SearchFieldLog;
import jp.sf.fess.db.exentity.SearchLog;
import jp.sf.fess.db.exentity.UserInfo;
import jp.sf.fess.helper.DocumentHelper;
@ -81,6 +82,18 @@ public class SearchLogHelperImpl extends SearchLogHelper {
botNames = value.split(",");
}
final boolean suggestAvailable = Constants.TRUE
.equals(crawlerProperties.getProperty(
Constants.SUGGEST_SEARCH_LOG_PROPERTY, Constants.TRUE));
final String dayForCleanupStr = crawlerProperties.getProperty(
Constants.PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY, "30");
int dayForCleanup = -1;
try {
dayForCleanup = Integer.parseInt(dayForCleanupStr);
} catch (final NumberFormatException e) {
}
boolean addedSuggest = false;
final Map<String, UserInfo> userInfoMap = new HashMap<String, UserInfo>();
for (final SearchLog searchLog : queue) {
boolean add = true;
@ -102,8 +115,23 @@ public class SearchLogHelperImpl extends SearchLogHelper {
userInfoMap.put(code, userInfo);
}
searchLogList.add(searchLog);
if (suggestAvailable && searchLog.getHitCount() > 0) {
final List<SearchFieldLog> searchFieldLogList = searchLog
.getSearchFieldLogList();
for (final SearchFieldLog searchFieldLog : searchFieldLogList) {
if ("solrQuery".equals(searchFieldLog.getName())) {
suggestService.addSolrParams(
searchFieldLog.getValue(), dayForCleanup);
addedSuggest = true;
}
}
}
}
}
if (addedSuggest) {
suggestService.commit();
}
if (!userInfoMap.isEmpty()) {
final List<UserInfo> insertList = new ArrayList<UserInfo>(

View file

@ -17,9 +17,7 @@
package jp.sf.fess.service;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -36,14 +34,9 @@ import jp.sf.fess.entity.MoreLikeThisInfo;
import jp.sf.fess.entity.PingResponse;
import jp.sf.fess.entity.SearchQuery;
import jp.sf.fess.entity.SearchQuery.SortField;
import jp.sf.fess.entity.SpellCheckResponse;
import jp.sf.fess.entity.SuggestResponse;
import jp.sf.fess.helper.QueryHelper;
import jp.sf.fess.helper.RoleQueryHelper;
import jp.sf.fess.solr.FessSolrQueryException;
import jp.sf.fess.suggest.SpellChecker;
import jp.sf.fess.suggest.SuggestConstants;
import jp.sf.fess.suggest.Suggester;
import jp.sf.fess.util.ComponentUtil;
import jp.sf.fess.util.QueryResponseList;
@ -64,21 +57,12 @@ public class SearchService implements Serializable {
@Resource
protected SolrGroupManager solrGroupManager;
@Resource
protected SolrGroup suggestSolrGroup;
@Resource
protected QueryHelper queryHelper;
@Resource
protected RoleQueryHelper roleQueryHelper;
@Resource
protected Suggester suggester;
@Resource
protected SpellChecker spellChecker;
public PingResponse ping() {
final SolrGroup solrGroup = solrGroupManager
.getSolrGroup(QueryType.QUERY);
@ -291,89 +275,6 @@ public class SearchService implements Serializable {
return queryResponseList;
}
public SuggestResponse getSuggestResponse(final String q,
final List<String> fieldNames, final List<String> labels,
final int rows) {
final Set<String> roleSet;
if (roleQueryHelper != null) {
roleSet = roleQueryHelper.build();
} else {
roleSet = new HashSet<>();
}
final List<String> roleList = new ArrayList<>(roleSet); // TODO
final String suggestQuery = suggester.buildSuggestQuery(q, fieldNames,
labels, roleList);
final long startTime = System.currentTimeMillis();
QueryResponse queryResponse = null;
final SolrQuery solrQuery = new SolrQuery();
if (StringUtil.isNotBlank(suggestQuery)) {
// query
solrQuery.setQuery(suggestQuery);
// size
solrQuery.setRows(rows);
//sort
solrQuery.setSort(SuggestConstants.SuggestFieldNames.COUNT,
SolrQuery.ORDER.desc);
if (queryHelper.getTimeAllowed() >= 0) {
solrQuery.setTimeAllowed(queryHelper.getTimeAllowed());
}
queryResponse = suggestSolrGroup.query(solrQuery,
SolrRequest.METHOD.POST);
}
final long execTime = System.currentTimeMillis() - startTime;
final SuggestResponse suggestResponse = new SuggestResponse(
queryResponse, rows, q);
suggestResponse.setExecTime(execTime);
return suggestResponse;
}
public SpellCheckResponse getSpellCheckResponse(final String q,
final List<String> fieldNames, final List<String> labels,
final int rows) {
final Set<String> roleSet;
if (roleQueryHelper != null) {
roleSet = roleQueryHelper.build();
} else {
roleSet = new HashSet<>();
}
final List<String> roleList = new ArrayList<>(roleSet);
final String spellCheckQuery = spellChecker.buildSpellCheckQuery(q,
fieldNames, labels, roleList);
final long startTime = System.currentTimeMillis();
QueryResponse queryResponse = null;
final SolrQuery solrQuery = new SolrQuery();
if (StringUtil.isNotBlank(spellCheckQuery)) {
// query
solrQuery.setQuery(spellCheckQuery);
// size
solrQuery.setRows(rows);
//sort
solrQuery.setSort(SuggestConstants.SuggestFieldNames.COUNT,
SolrQuery.ORDER.desc);
if (queryHelper.getTimeAllowed() >= 0) {
solrQuery.setTimeAllowed(queryHelper.getTimeAllowed());
}
queryResponse = suggestSolrGroup.query(solrQuery,
SolrRequest.METHOD.POST);
}
final long execTime = System.currentTimeMillis() - startTime;
final SpellCheckResponse spellCheckResponse = new SpellCheckResponse(
queryResponse, rows, q);
spellCheckResponse.setExecTime(execTime);
return spellCheckResponse;
}
public FieldAnalysisResponse getFieldAnalysisResponse(
final String[] fieldNames, final String fieldValue) {
final FieldAnalysisRequest request = new FieldAnalysisRequest();

View file

@ -7,7 +7,6 @@
<include path="dbflute.dicon"/>
<include path="fess.dicon"/>
<include path="fess_suggest.dicon"/>
<include path="fess_job.dicon"/>
<include path="fess_api.dicon"/>
<include path="fess_dict.dicon"/>

View file

@ -680,6 +680,13 @@ labels.system_index_status=Index Status
labels.crawler_status_title=Crawler Status
labels.crawler_sessionid_all=All
labels.no_available_solr_servers=No available Solr server.
labels.suggest_document_title=Added Suggest Docs
labels.suggest_type=type
labels.suggest_type_all=all
labels.suggest_type_content=content
labels.suggest_type_searchlog=search words
labels.suggest_search_log_enabled=Suggest by Search Words
labels.purge_suggest_search_log_day=Purge Suggest Docs by Search Words
# view/admin/crawlingSession/confirm.jsp
labels.crawling_session_title=Session Information

View file

@ -680,6 +680,13 @@ labels.system_index_status=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u72b6\u614b
labels.crawler_status_title=\u30af\u30ed\u30fc\u30e9\u30fc\u72b6\u614b
labels.crawler_sessionid_all=\u3059\u3079\u3066
labels.no_available_solr_servers=\u5229\u7528\u53ef\u80fd\u306aSolr\u30b5\u30fc\u30d0\u304c\u3042\u308a\u307e\u305b\u3093\u3002
labels.suggest_document_title=\u8FFD\u52A0\u3055\u308C\u305F\u30B5\u30B8\u30A7\u30B9\u30C8\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8
labels.suggest_type=\u7A2E\u5225
labels.suggest_type_all=\u3059\u3079\u3066
labels.suggest_type_content=\u30B3\u30F3\u30C6\u30F3\u30C4
labels.suggest_type_searchlog=\u691C\u7D22\u30ED\u30B0
labels.suggest_search_log_enabled=\u691C\u7D22\u8A9E\u30B5\u30B8\u30A7\u30B9\u30C8
labels.purge_suggest_search_log_day=\u691C\u7D22\u8A9E\u30B5\u30B8\u30A7\u30B9\u30C8\u306E\u6709\u52B9\u671F\u9650
# view/admin/crawlingSession/confirm.jsp
labels.crawling_session_title=\u30bb\u30c3\u30b7\u30e7\u30f3\u60c5\u5831

View file

@ -4,6 +4,7 @@
<components>
<include path="solrlib.dicon"/>
<include path="fess_ds.dicon"/>
<include path="fess_suggest.dicon"/>
<component name="crawlerProperties" class="org.codelibs.core.util.DynamicProperties">
<arg>

View file

@ -45,63 +45,9 @@
</initMethod>
</component>
<!-- Solr Group Configuration -->
<component name="suggestSolrProperties" class="org.codelibs.core.util.DynamicProperties">
<arg>
@jp.sf.fess.util.ResourceUtil@getConfPath("solr-suggest.properties")
</arg>
</component>
<component name="suggestSolrGroupProperties" class="org.codelibs.core.util.DynamicProperties">
<arg>
@jp.sf.fess.util.ResourceUtil@getConfPath("suggestSolrGroup.properties")
</arg>
</component>
<component name="suggestSolrGroup" class="org.codelibs.solr.lib.SolrGroup">
<!-- Note: groupName cannot include ".". -->
<property name="groupName">"suggestSolrGroup"</property>
<property name="statusPolicy">
<component class="jp.sf.fess.solr.policy.FessStatusPolicy">
<property name="solrGroupProperties">suggestSolrGroupProperties</property>
<property name="minSelectServer">1</property>
<property name="minUpdateServer">1</property>
<property name="retrySelectQueryInterval">500</property>
<property name="retryUpdateQueryInterval">500</property>
<property name="maxErrorCount">3</property>
<property name="maxRetryUpdateQueryCount">3</property>
<property name="maxRetrySelectQueryCount">3</property>
</component>
</property>
<initMethod name="addServer">
<!-- Note: the server name cannot include ".". -->
<arg>"suggestSolrServer"</arg><!-- Group Name -->
<arg>suggestSolrServer</arg><!-- Solr Server -->
</initMethod>
</component>
<component name="clientConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
<arg>10</arg><!-- timeToLive -->
<arg>@java.util.concurrent.TimeUnit@MINUTES</arg><!-- tunit -->
<property name="maxTotal">50</property>
<property name="defaultMaxPerRoute">2</property>
<destroyMethod name="shutdown"></destroyMethod>
</component>
<component name="connectionMonitorTarget" class="org.codelibs.robot.client.http.HcConnectionMonitorTarget">
<arg>clientConnectionManager</arg>
<arg>300000</arg>
</component>
<component name="connectionMonitorTask">
@org.seasar.extension.timer.TimeoutManager@getInstance()
.addTimeoutTarget(
connectionMonitorTarget,
10,
true)
<destroyMethod name="cancel"></destroyMethod>
</component>
<!-- Solr Server Configuration -->
<component name="suggestSolrServer" class="org.codelibs.solr.lib.server.SolrLibHttpSolrServer">
<component name="suggestSolrLibSolrServer" class="org.codelibs.solr.lib.server.SolrLibHttpSolrServer">
<!-- Solr Server URL -->
<arg>"http://localhost:8080/solr/core1-suggest"</arg>
<property name="requestWriter">new org.apache.solr.client.solrj.impl.BinaryRequestWriter()</property>
@ -126,4 +72,16 @@
<destroyMethod name="shutdown"></destroyMethod>
</component>
<component name="suggestSolrServer" class="jp.sf.fess.suggest.server.SuggestSolrServer">
<arg>
suggestSolrLibSolrServer
</arg>
</component>
<component name="suggestService" class="jp.sf.fess.suggest.service.SuggestService">
<arg> suggester </arg>
<arg> spellchecker </arg>
<arg> suggestSolrServer </arg>
</component>
</components>

View file

@ -207,6 +207,22 @@
<html:text property="failureCountThreshold" styleClass="small"/>
</td>
</tr>
<tr>
<th style="width:200px;">
<bean:message key="labels.suggest_search_log_enabled"/>
</th>
<td>
<html:checkbox property="suggestSearchLog"/><bean:message key="labels.enabled"/>
</td>
</tr>
<tr>
<th>
<bean:message key="labels.purge_suggest_search_log_day"/>
</th>
<td>
<html:text property="purgeSuggestSearchLogDay" styleClass="small"/>
</td>
</tr>
</tbody>
<tfoot>
<tr>

View file

@ -141,7 +141,65 @@
</tbody>
</table>
</div>
</c:if>
<div style="margin-top: 5px;">
<h3>
<bean:message key="labels.suggest_document_title" />
</h3>
<table class="bordered-table zebra-striped">
<thead>
<tr>
<th style="width:200px;"><bean:message key="labels.suggest_type" /></th>
<th><bean:message key="labels.solr_num_of_docs" /></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><bean:message key="labels.suggest_type_all" /></td>
<td align="center">${suggestDocumentNums.all}</td>
<td align="center">
<s:form>
<html:hidden property="deleteSuggestType"
value="all" />
<html:submit styleClass="btn" property="deleteSuggest"
disabled="${solrProcessRunning}">
<bean:message key="labels.solr_action_delete" />
</html:submit>
</s:form>
</td>
</tr>
<tr>
<td><bean:message key="labels.suggest_type_content" /></td>
<td align="center">${suggestDocumentNums.content}</td>
<td align="center">
<s:form>
<html:hidden property="deleteSuggestType"
value="content" />
<html:submit styleClass="btn" property="deleteSuggest"
disabled="${solrProcessRunning}">
<bean:message key="labels.solr_action_delete" />
</html:submit>
</s:form>
</td>
</tr>
<tr>
<td><bean:message key="labels.suggest_type_searchlog" /></td>
<td align="center">${suggestDocumentNums.searchLog}</td>
<td align="center">
<s:form>
<html:hidden property="deleteSuggestType"
value="searchLog" />
<html:submit styleClass="btn" property="deleteSuggest"
disabled="${solrProcessRunning}">
<bean:message key="labels.solr_action_delete" />
</html:submit>
</s:form>
</td>
</tr>
</tbody>
</table>
</div>
</c:if>
</div>
<c:if test="${solrProcessRunning}">