add single query method

This commit is contained in:
luke 2025-05-21 22:54:40 +08:00
parent 21a1179765
commit 62791e5553

View File

@ -6,9 +6,11 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.*; import org.elasticsearch.client.*;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder; import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -40,21 +42,8 @@ public class SearchController {
int size = requestBody.getSize() != null && requestBody.getSize() > 0 ? requestBody.getSize() : defaultPageSize; int size = requestBody.getSize() != null && requestBody.getSize() > 0 ? requestBody.getSize() : defaultPageSize;
int from = (page - 1) * size; int from = (page - 1) * size;
// 构建外层 OR 查询
BoolQueryBuilder outerQuery = QueryBuilders.boolQuery();
for (List<String> group : requestBody.getKeywordGroups()) {
BoolQueryBuilder groupQuery = QueryBuilders.boolQuery();
for (String keyword : group) {
// 使用 match_phrase 精确匹配短语
groupQuery.must(QueryBuilders.multiMatchQuery(keyword, "filename", "content")
.type(MultiMatchQueryBuilder.Type.PHRASE));
}
outerQuery.should(groupQuery);
}
outerQuery.minimumShouldMatch(1); // 至少匹配一组
SearchSourceBuilder builder = new SearchSourceBuilder() SearchSourceBuilder builder = new SearchSourceBuilder()
.query(outerQuery) .query(buildSearchQuery(requestBody.getKeywordGroups()))
.from(from) .from(from)
.size(size) .size(size)
.sort("mtime", SortOrder.DESC); .sort("mtime", SortOrder.DESC);
@ -62,7 +51,50 @@ public class SearchController {
SearchRequest request = new SearchRequest("documents").source(builder); SearchRequest request = new SearchRequest("documents").source(builder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT); SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
return buildSearchResponse(response, requestBody.getFlatKeywords(), page, size);
}
@GetMapping
public Map<String, Object> search(@RequestParam String q) throws IOException {
int page = 1;
int size = defaultPageSize;
int from = 0;
// 单关键词转换成一组组结构
List<List<String>> keywordGroups = Collections.singletonList(Collections.singletonList(q));
List<String> flatKeywords = Collections.singletonList(q);
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(buildSearchQuery(keywordGroups))
.from(from)
.size(size)
.sort("mtime", SortOrder.DESC);
SearchRequest request = new SearchRequest("documents").source(builder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
return buildSearchResponse(response, flatKeywords, page, size);
}
private QueryBuilder buildSearchQuery(List<List<String>> keywordGroups) {
BoolQueryBuilder outerQuery = QueryBuilders.boolQuery();
for (List<String> group : keywordGroups) {
BoolQueryBuilder groupQuery = QueryBuilders.boolQuery();
for (String keyword : group) {
groupQuery.must(QueryBuilders.multiMatchQuery(keyword, "filename", "content")
.type(MultiMatchQueryBuilder.Type.PHRASE));
}
outerQuery.should(groupQuery);
}
outerQuery.minimumShouldMatch(1);
return outerQuery;
}
private Map<String, Object> buildSearchResponse(SearchResponse response, List<String> keywords, int page, int size) {
List<Map<String, Object>> results = new ArrayList<>(); List<Map<String, Object>> results = new ArrayList<>();
for (SearchHit hit : response.getHits()) { for (SearchHit hit : response.getHits()) {
Map<String, Object> source = hit.getSourceAsMap(); Map<String, Object> source = hit.getSourceAsMap();
Map<String, Object> result = new LinkedHashMap<>(); Map<String, Object> result = new LinkedHashMap<>();
@ -71,7 +103,7 @@ public class SearchController {
result.put("mtime", source.get("mtime")); result.put("mtime", source.get("mtime"));
String content = (String) source.get("content"); String content = (String) source.get("content");
String summary = extractMultiSnippet(content, requestBody.getFlatKeywords(), 50); String summary = extractMultiSnippet(content, keywords, 50);
result.put("summary", summary); result.put("summary", summary);
results.add(result); results.add(result);
@ -85,6 +117,7 @@ public class SearchController {
return responseBody; return responseBody;
} }
private String extractMultiSnippet(String content, List<String> keywords, int contextLength) { private String extractMultiSnippet(String content, List<String> keywords, int contextLength) {
if (content == null || keywords == null || keywords.isEmpty()) return ""; if (content == null || keywords == null || keywords.isEmpty()) return "";