瀏覽代碼

Add delete all with this query

Kaoru FUZITA 9 年之前
父節點
當前提交
2ff1031e43

+ 2 - 0
src/main/java/org/codelibs/fess/Constants.java

@@ -296,6 +296,8 @@ public class Constants extends CoreLibConstants {
 
     public static final String FACET_QUERY_PREFIX = "query:";
 
+    public static final String MATCHES_ALL_QUERY = "*:*";
+
     public static final String FESS_ES_TRANSPORT_ADDRESSES = "fess.es.transport_addresses";
 
     public static final String FESS_ES_CLUSTER_NAME = "fess.es.cluster_name";

+ 36 - 0
src/main/java/org/codelibs/fess/app/service/SearchService.java

@@ -36,6 +36,7 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.web.base.login.FessLoginAssist;
+import org.codelibs.fess.entity.QueryContext;
 import org.codelibs.fess.entity.SearchRenderData;
 import org.codelibs.fess.entity.SearchRequestParams;
 import org.codelibs.fess.es.client.FessEsClient;
@@ -195,6 +196,41 @@ public class SearchService {
         }
     }
 
+    public int deleteByQuery(final HttpServletRequest request, final SearchRequestParams params) {
+        if (StringUtil.isNotBlank(params.getOperator())) {
+            request.setAttribute(Constants.DEFAULT_OPERATOR, params.getOperator());
+        }
+
+        final StringBuilder queryBuf = new StringBuilder(255);
+        if (StringUtil.isNotBlank(params.getQuery())) {
+            if (params.getQuery().indexOf(" OR ") >= 0) {
+                queryBuf.append('(').append(params.getQuery()).append(')');
+            } else {
+                queryBuf.append(params.getQuery());
+            }
+        }
+        if (params.getAdditional() != null) {
+            appendAdditionalQuery(params.getAdditional(), additional -> {
+                queryBuf.append(' ').append(additional);
+            });
+        }
+        params.getFields().entrySet().stream().forEach(entry -> {
+            appendQueries(queryBuf, entry.getKey(), entry.getValue());
+        });
+
+        if (params.getLanguages() != null) {
+            appendQueries(queryBuf, fessConfig.getIndexFieldLang(), params.getLanguages());
+        }
+
+        final String query = queryBuf.toString().trim();
+
+        final QueryContext queryContext = queryHelper.build(query, context -> {
+            context.skipRoleQuery();
+        });
+        return fessEsClient.deleteByQuery(fessConfig.getIndexDocumentIndex(), fessConfig.getIndexDocumentType(),
+                queryContext.getQueryBuilder());
+    }
+
     protected void storeSearchLog(final HttpServletRequest request, final LocalDateTime requestedTime, final String queryId,
             final String query, final int pageStart, final int pageSize, final QueryResponseList queryResponseList) {
 

+ 44 - 13
src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java

@@ -22,6 +22,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 
 import org.codelibs.core.lang.StringUtil;
+import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.service.SearchService;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.entity.SearchRenderData;
@@ -109,19 +110,19 @@ public class AdminSearchlistAction extends FessAdminAction {
     // ==============
     @Execute
     public HtmlResponse index(final ListForm form) {
+        saveToken();
         validate(form, messages -> {}, () -> asHtml(path_AdminError_AdminErrorJsp));
-        return asHtml(path_AdminSearchlist_AdminSearchlistJsp);
+        return asListHtml();
     }
 
     protected HtmlResponse doSearch(final ListForm form) {
-        validate(form, messages -> {}, () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+        validate(form, messages -> {}, () -> asListHtml());
 
         if (StringUtil.isBlank(form.query)) {
-            // redirect to index page
-            form.query = null;
-            return redirect(getClass());
+            // query matches on all documents.
+            form.query = Constants.MATCHES_ALL_QUERY;
         }
-        return asHtml(path_AdminSearchlist_AdminSearchlistJsp).renderWith(data -> {
+        return asListHtml().renderWith(data -> {
             doSearchInternal(data, form);
         });
     }
@@ -135,7 +136,7 @@ public class AdminSearchlistAction extends FessAdminAction {
             if (logger.isDebugEnabled()) {
                 logger.debug(e.getMessage(), e);
             }
-            throwValidationError(e.getMessageCode(), () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(e.getMessageCode(), () -> asListHtml());
         } catch (final ResultOffsetExceededException e) {
             if (logger.isDebugEnabled()) {
                 logger.debug(e.getMessage(), e);
@@ -148,21 +149,25 @@ public class AdminSearchlistAction extends FessAdminAction {
 
     @Execute
     public HtmlResponse search(final ListForm form) {
+        saveToken();
         return doSearch(form);
     }
 
     @Execute
     public HtmlResponse prev(final ListForm form) {
+        saveToken();
         return doMove(form, -1);
     }
 
     @Execute
     public HtmlResponse next(final ListForm form) {
+        saveToken();
         return doMove(form, 1);
     }
 
     @Execute
     public HtmlResponse move(final ListForm form) {
+        saveToken();
         return doMove(form, 0);
     }
 
@@ -185,27 +190,53 @@ public class AdminSearchlistAction extends FessAdminAction {
 
     @Execute
     public HtmlResponse delete(final DeleteForm form) {
-        validate(form, messages -> {}, () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+        verifyToken(() -> asListHtml());
+        validate(form, messages -> {}, () -> asListHtml());
         final String docId = form.docId;
         if (jobHelper.isCrawlProcessRunning()) {
-            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL),
-                    () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml());
         }
         try {
             final QueryBuilder query = QueryBuilders.termQuery(fessConfig.getIndexFieldDocId(), docId);
             fessEsClient.deleteByQuery(fessConfig.getIndexDocumentIndex(), fessConfig.getIndexDocumentType(), query);
             saveInfo(messages -> messages.addSuccessDeleteDocFromIndex(GLOBAL));
         } catch (final Exception e) {
-            throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL),
-                    () -> asHtml(path_AdminSearchlist_AdminSearchlistJsp));
+            throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL), () -> asListHtml());
+        }
+        return asListHtml();
+    }
+
+    @Execute
+    public HtmlResponse deleteall(final ListForm form) {
+        verifyToken(() -> asListHtml());
+        validate(form, messages -> {}, () -> asListHtml());
+        if (jobHelper.isCrawlProcessRunning()) {
+            throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml());
+        }
+        try {
+            searchService.deleteByQuery(request, form);
+            saveInfo(messages -> messages.addSuccessDeleteDocFromIndex(GLOBAL));
+        } catch (final InvalidQueryException e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug(e.getMessage(), e);
+            }
+            throwValidationError(e.getMessageCode(), () -> asListHtml());
         }
-        return redirectWith(getClass(), moreUrl("search").params("query", form.query));
+        return asListHtml();
     }
 
     public boolean isSolrProcessRunning() {
         return jobHelper.isCrawlProcessRunning();
     }
 
+    // ===================================================================================
+    //                                                                              JSP
+    //                                                                           =========
+
+    private HtmlResponse asListHtml() {
+        return asHtml(path_AdminSearchlist_AdminSearchlistJsp);
+    }
+
     protected static class WebRenderData extends SearchRenderData {
         private final RenderData data;
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/config/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
                 builder.setSearchType(searchType);
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/config/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
             boolQuery.filter(query);
         });
-        regQ(boolQuery);
         return boolQuery;
     }
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/log/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
                 builder.setSearchType(searchType);
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/log/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
             boolQuery.filter(query);
         });
-        regQ(boolQuery);
         return boolQuery;
     }
 

+ 1 - 1
src/main/java/org/codelibs/fess/es/user/allcommon/EsAbstractConditionBean.java

@@ -654,7 +654,7 @@ public abstract class EsAbstractConditionBean implements ConditionBean {
             if (searchType != null) {
                 builder.setSearchType(searchType);
             }
-            if (timeoutInMillis != -1) {
+            if (timeoutInMillis == -1) {
                 builder.setTimeout(new TimeValue(timeoutInMillis));
             }
             if (version != null) {

+ 0 - 1
src/main/java/org/codelibs/fess/es/user/allcommon/EsAbstractConditionQuery.java

@@ -164,7 +164,6 @@ public abstract class EsAbstractConditionQuery implements ConditionQuery {
         filterList.forEach(query -> {
             boolQuery.filter(query);
         });
-        regQ(boolQuery);
         return boolQuery;
     }
 

+ 3 - 0
src/main/java/org/codelibs/fess/helper/QueryHelper.java

@@ -40,6 +40,7 @@ import org.apache.lucene.queryparser.ext.ExtendableQueryParser;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TermQuery;
@@ -299,6 +300,8 @@ public class QueryHelper implements Serializable {
         } else if (query instanceof BooleanQuery) {
             final BooleanQuery booleanQuery = (BooleanQuery) query;
             return convertBooleanQuery(context, booleanQuery);
+        } else if (query instanceof MatchAllDocsQuery) {
+            return QueryBuilders.matchAllQuery();
         }
         throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(ActionMessages.GLOBAL_PROPERTY_KEY),
                 "Unknown query: " + query.getClass() + " => " + query);

+ 11 - 5
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -1488,14 +1488,20 @@ public class FessLabels extends ActionMessages {
     public static final String LABELS_search_list_configuration = "{labels.search_list_configuration}";
 
     /** The key of the message: Delete */
-    public static final String LABELS_search_list_delete_link = "{labels.search_list_delete_link}";
+    public static final String LABELS_search_list_button_delete = "{labels.search_list_button_delete}";
 
-    /** The key of the message: Cancel */
-    public static final String LABELS_search_list_delete_cancel = "{labels.search_list_delete_cancel}";
-
-    /** The key of the message: Do you really want to delete? ({0}) */
+    /** The key of the message: Do you really want to delete? */
     public static final String LABELS_search_list_delete_confirmation = "{labels.search_list_delete_confirmation}";
 
+    /** The key of the message: Delete all with this query */
+    public static final String LABELS_search_list_button_delete_all = "{labels.search_list_button_delete_all}";
+
+    /** The key of the message: Do you really want to delete all with this query? */
+    public static final String LABELS_search_list_delete_all_confirmation = "{labels.search_list_delete_all_confirmation}";
+
+    /** The key of the message: Cancel */
+    public static final String LABELS_search_list_button_cancel = "{labels.search_list_button_cancel}";
+
     /** The key of the message: Failure URL */
     public static final String LABELS_failure_url_configuration = "{labels.failure_url_configuration}";
 

+ 5 - 3
src/main/resources/fess_label.properties

@@ -493,9 +493,11 @@ labels.wizard_start_crawling_desc=To click "Start Crawling" button, you can star
 labels.wizard_button_start_crawling=Start Crawling
 labels.wizard_button_finish=Skip
 labels.search_list_configuration=Search
-labels.search_list_delete_link=Delete
-labels.search_list_delete_cancel=Cancel
-labels.search_list_delete_confirmation=Do you really want to delete? ({0})
+labels.search_list_button_delete=Delete
+labels.search_list_delete_confirmation=Do you really want to delete?
+labels.search_list_button_delete_all=Delete all with this query
+labels.search_list_delete_all_confirmation=Do you really want to delete all with this query?
+labels.search_list_button_cancel=Cancel
 labels.failure_url_configuration=Failure URL
 labels.failure_url_search_url=URL
 labels.failure_url_search_error_count=Error Count

+ 2 - 1
src/main/webapp/WEB-INF/view/admin/crawlinginfo/admin_crawlinginfo.jsp

@@ -55,7 +55,8 @@
 													styleClass="form-control" placeholder="${ph_session_id}"></la:text>
 											</div>
 											<div class="form-group">
-												<button type="submit" class="btn btn-primary" name="search"
+												<button type="submit" class="btn btn-primary" id="submit"
+													name="search"
 													value="<la:message key="labels.crawling_session_search" />">
 													<i class="fa fa-search"></i>
 													<la:message key="labels.crawling_session_search" />

+ 2 - 1
src/main/webapp/WEB-INF/view/admin/failureurl/admin_failureurl.jsp

@@ -70,7 +70,8 @@
 									</div>
 									<div class="form-group">
 										<div class="col-sm-offset-2 col-sm-10">
-											<button type="submit" class="btn btn-primary" name="search"
+											<button type="submit" class="btn btn-primary" id="submit"
+												name="search"
 												value="<la:message key="labels.crud_button_search" />">
 												<i class="fa fa-search"></i>
 												<la:message key="labels.crud_button_search" />

+ 104 - 56
src/main/webapp/WEB-INF/view/admin/searchlist/admin_searchlist.jsp

@@ -51,8 +51,8 @@
 											placeholder="Type a search query" />
 									</div>
 									<div class="form-group">
-										<button type="submit" class="btn btn-primary" name="search"
-											value="<la:message key="labels.search"/>">
+										<button type="submit" class="btn btn-primary" id="submit"
+											name="search" value="<la:message key="labels.search"/>">
 											<i class="fa fa-search"></i>
 											<la:message key="labels.search" />
 										</button>
@@ -83,60 +83,17 @@
 															<a href="${doc.urlLink}">${f:h(doc.contentTitle)}</a>
 														</h3>
 														<div class="body col-sm-11">
-															${doc.contentDescription}</div> <c:if
-															test="${!crawlerProcessRunning}">
-															<button type="button"
-																class="btn btn-xs btn-danger col-sm-1"
-																data-toggle="modal" data-target="#confirmToDelete">
-																<i class="fa fa-trash"></i>
-																<la:message key="labels.search_list_delete_link" />
-															</button>
-															<div class="modal modal-danger fade" id="confirmToDelete"
-																tabindex="-1" role="dialog">
-																<div class="modal-dialog">
-																	<div class="modal-content">
-																		<div class="modal-header">
-																			<button type="button" class="close"
-																				data-dismiss="modal" aria-label="Close">
-																				<span aria-hidden="true">×</span>
-																			</button>
-																			<h4 class="modal-title">
-																				<la:message key="labels.search_list_delete_link" />
-																			</h4>
-																		</div>
-																		<div class="modal-body">
-																			<p>
-																				<la:message
-																					key="labels.search_list_delete_confirmation"
-																					arg0="${f:h(doc.urlLink)}" />
-																			</p>
-																		</div>
-																		<div class="modal-footer">
-																			<button type="button"
-																				class="btn btn-outline pull-left"
-																				data-dismiss="modal">
-																				<la:message key="labels.search_list_delete_cancel" />
-																			</button>
-																			<la:form action="delete">
-																				<%-- TODO: doc_id --%>
-																				<la:hidden property="docId"
-																					value="${f:u(doc.doc_id)}" />
-																				<la:hidden property="query" value="${f:u(query)}" />
-																				<button type="submit"
-																					class="btn btn-outline btn-danger">
-																					<i class="fa fa-trash"></i>
-																					<la:message key="labels.search_list_delete_link" />
-																				</button>
-																			</la:form>
-																		</div>
-																	</div>
-																</div>
-															</div>
-														</c:if> <c:if test="${crawlerProcessRunning}">
-															<div class="col-sm-1">
-																<la:message key="labels.search_list_delete_link" />
-															</div>
-														</c:if>
+															${doc.contentDescription}</div>
+														<button type="button"
+															class="btn btn-xs btn-danger col-sm-1"
+															data-toggle="modal" data-target="#confirmToDelete"
+															data-docid="${f:u(doc.doc_id)}"
+															data-title="${f:h(doc.contentTitle)}"
+															data-url="${f:h(doc.urlLink)}"
+															<c:if test="${crawlerProcessRunning}">disable</c:if>>
+															<i class="fa fa-trash"></i>
+															<la:message key="labels.search_list_button_delete" />
+														</button>
 													</li>
 												</c:forEach>
 											</ol>
@@ -189,8 +146,99 @@
 										</div>
 									</c:otherwise>
 								</c:choose>
+								<div class="modal modal-danger fade" id="confirmToDelete"
+									tabindex="-1" role="dialog">
+									<div class="modal-dialog">
+										<div class="modal-content">
+											<div class="modal-header">
+												<button type="button" class="close" data-dismiss="modal"
+													aria-label="Close">
+													<span aria-hidden="true">×</span>
+												</button>
+												<h4 class="modal-title">
+													<la:message key="labels.search_list_button_delete" />
+												</h4>
+											</div>
+											<div class="modal-body">
+												<p>
+													<la:message key="labels.search_list_delete_confirmation" />
+												</p>
+												<p>
+													<strong id="delete-doc-title"></strong><br /> <span
+														id="delete-doc-url"></span>
+												</p>
+											</div>
+											<div class="modal-footer">
+												<button type="button" class="btn btn-outline pull-left"
+													data-dismiss="modal">
+													<la:message key="labels.search_list_button_cancel" />
+												</button>
+												<la:form action="/admin/searchlist/delete">
+													<input type="hidden" name="docId" id="docId" />
+													<button type="submit" class="btn btn-outline btn-danger"
+														name="delete"
+														value="<la:message key="labels.search_list_button_delete" />">
+														<i class="fa fa-trash"></i>
+														<la:message key="labels.search_list_button_delete" />
+													</button>
+												</la:form>
+											</div>
+										</div>
+									</div>
+								</div>
 							</div>
 							<!-- /.box-body -->
+							<div class="box-footer">
+								<c:if test="${f:h(allRecordCount) > 0}">
+									<div class="row">
+										<div class="col-sm-12 center">
+											<button type="button" class="btn btn-danger"
+												data-toggle="modal" data-target="#confirmToDeleteAll">
+												<i class="fa fa-trash"></i>
+												<la:message key="labels.search_list_button_delete_all" />
+											</button>
+										</div>
+										<div class="modal modal-danger fade" id="confirmToDeleteAll"
+											tabindex="-1" role="dialog">
+											<div class="modal-dialog">
+												<div class="modal-content">
+													<div class="modal-header">
+														<button type="button" class="close" data-dismiss="modal"
+															aria-label="Close">
+															<span aria-hidden="true">×</span>
+														</button>
+														<h4 class="modal-title">
+															<la:message key="labels.search_list_button_delete_all" />
+														</h4>
+													</div>
+													<div class="modal-body">
+														<p>
+															<la:message
+																key="labels.search_list_delete_all_confirmation" />
+														</p>
+													</div>
+													<div class="modal-footer">
+														<la:form action="/admin/searchlist/deleteall">
+															<la:hidden property="query" />
+															<button type="button" class="btn btn-outline pull-left"
+																data-dismiss="modal">
+																<la:message key="labels.search_list_button_cancel" />
+															</button>
+															<button type="submit" class="btn btn-outline btn-danger"
+																name="deleteall"
+																value="<la:message key="labels.search_list_button_delete_all" />">
+																<i class="fa fa-trash"></i>
+																<la:message key="labels.search_list_button_delete_all" />
+															</button>
+														</la:form>
+													</div>
+												</div>
+											</div>
+										</div>
+									</div>
+								</c:if>
+							</div>
+							<!-- /.box-footer -->
 						</div>
 						<!-- /.box -->
 					</div>

+ 17 - 1
src/main/webapp/js/admin/admin.js

@@ -1,8 +1,13 @@
 $(function() {
-	$('input[type="text"],select', '.login-box,section.content').first().focus();
+	$('input[type="text"],select', '.login-box,section.content').first()
+			.focus();
 
 	$("section.content input").keypress(function(e) {
 		if (e.which == 13) {
+			var $submitButton = $('input#submit, button#submit');
+			if ($submitButton.size() > 0) {
+				$submitButton[0].submit();
+			}
 			// ignore enter key down
 			return false;
 		}
@@ -17,4 +22,15 @@ $(function() {
 			document.location = $(this).attr('data-href');
 		});
 	});
+
+	$('#confirmToDelete').on('show.bs.modal', function(event) {
+		var button = $(event.relatedTarget);
+		var docId = button.data('docid');
+		var title = button.data('title');
+		var url = button.data('url');
+
+		$(this).find('.modal-body #delete-doc-title').text(title);
+		$(this).find('.modal-body #delete-doc-url').text(url);
+		$(this).find('.modal-footer input#docId').val(docId);
+	})
 });