mirror of https://github.com/halo-dev/halo
Support filtering search result by types, ownerNames, categoryNames and tagNames (#6442)
#### What type of PR is this? /kind improvement /area core #### What this PR does / why we need it: This PR allows users to filter search result by types, owner names, category names and tag names. #### Does this PR introduce a user-facing change? ```release-note 完善搜索引擎过滤功能 ```pull/6453/head
parent
457508f1cd
commit
40386557a7
|
@ -53,22 +53,22 @@ public class SearchOption {
|
||||||
private Boolean filterPublished;
|
private Boolean filterPublished;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types to include. If null, it will include all types.
|
* Types to include(or). If null, it will include all types.
|
||||||
*/
|
*/
|
||||||
private List<String> includeTypes;
|
private List<String> includeTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owner names to include. If null, it will include all owners.
|
* Owner names to include(or). If null, it will include all owners.
|
||||||
*/
|
*/
|
||||||
private List<String> includeOwnerNames;
|
private List<String> includeOwnerNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category names to include. If null, it will include all categories.
|
* Category names to include(and). If null, it will include all categories.
|
||||||
*/
|
*/
|
||||||
private List<String> includeCategoryNames;
|
private List<String> includeCategoryNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag names to include. If null, it will include all tags.
|
* Tag names to include(and). If null, it will include all tags.
|
||||||
*/
|
*/
|
||||||
private List<String> includeTagNames;
|
private List<String> includeTagNames;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.charfilter.HTMLStripCharFilterFactory;
|
import org.apache.lucene.analysis.charfilter.HTMLStripCharFilterFactory;
|
||||||
|
@ -170,6 +171,45 @@ public class LuceneSearchEngine implements SearchEngine, InitializingBean, Dispo
|
||||||
new TermQuery(new Term("published", filterPublished.toString())), FILTER
|
new TermQuery(new Term("published", filterPublished.toString())), FILTER
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional.ofNullable(option.getIncludeTypes())
|
||||||
|
.filter(types -> !types.isEmpty())
|
||||||
|
.ifPresent(types -> {
|
||||||
|
var typeTerms = types.stream()
|
||||||
|
.distinct()
|
||||||
|
.map(BytesRef::new)
|
||||||
|
.toList();
|
||||||
|
queryBuilder.add(new TermInSetQuery("type", typeTerms), FILTER);
|
||||||
|
});
|
||||||
|
|
||||||
|
Optional.ofNullable(option.getIncludeOwnerNames())
|
||||||
|
.filter(ownerNames -> !ownerNames.isEmpty())
|
||||||
|
.ifPresent(ownerNames -> {
|
||||||
|
var ownerTerms = ownerNames.stream()
|
||||||
|
.distinct()
|
||||||
|
.map(BytesRef::new)
|
||||||
|
.toList();
|
||||||
|
queryBuilder.add(new TermInSetQuery("ownerName", ownerTerms), FILTER);
|
||||||
|
});
|
||||||
|
|
||||||
|
Optional.ofNullable(option.getIncludeTagNames())
|
||||||
|
.filter(tagNames -> !tagNames.isEmpty())
|
||||||
|
.ifPresent(tagNames -> tagNames
|
||||||
|
.stream()
|
||||||
|
.distinct()
|
||||||
|
.forEach(tagName ->
|
||||||
|
queryBuilder.add(new TermQuery(new Term("tag", tagName)), FILTER)
|
||||||
|
));
|
||||||
|
|
||||||
|
Optional.ofNullable(option.getIncludeCategoryNames())
|
||||||
|
.filter(categoryNames -> !categoryNames.isEmpty())
|
||||||
|
.ifPresent(categoryNames -> categoryNames
|
||||||
|
.stream()
|
||||||
|
.distinct()
|
||||||
|
.forEach(categoryName ->
|
||||||
|
queryBuilder.add(new TermQuery(new Term("category", categoryName)), FILTER)
|
||||||
|
));
|
||||||
|
|
||||||
var finalQuery = queryBuilder.build();
|
var finalQuery = queryBuilder.build();
|
||||||
var limit = option.getLimit();
|
var limit = option.getLimit();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import static run.halo.app.core.extension.content.Post.VisibleEnum.PRIVATE;
|
||||||
import static run.halo.app.core.extension.content.Post.VisibleEnum.PUBLIC;
|
import static run.halo.app.core.extension.content.Post.VisibleEnum.PUBLIC;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -122,6 +123,9 @@ public class LuceneSearchEngineIntegrationTest {
|
||||||
option.setKeyword("halo");
|
option.setKeyword("halo");
|
||||||
option.setHighlightPreTag("<my-tag>");
|
option.setHighlightPreTag("<my-tag>");
|
||||||
option.setHighlightPostTag("</my-tag>");
|
option.setHighlightPostTag("</my-tag>");
|
||||||
|
option.setIncludeTagNames(List.of("search"));
|
||||||
|
option.setIncludeCategoryNames(List.of("halo"));
|
||||||
|
option.setIncludeOwnerNames(List.of("admin"));
|
||||||
retryTemplate.execute(context -> {
|
retryTemplate.execute(context -> {
|
||||||
webClient.post().uri("/apis/api.halo.run/v1alpha1/indices/-/search")
|
webClient.post().uri("/apis/api.halo.run/v1alpha1/indices/-/search")
|
||||||
.bodyValue(option)
|
.bodyValue(option)
|
||||||
|
@ -218,6 +222,8 @@ public class LuceneSearchEngineIntegrationTest {
|
||||||
spec.setPriority(0);
|
spec.setPriority(0);
|
||||||
spec.setSlug("/first-post");
|
spec.setSlug("/first-post");
|
||||||
spec.setDeleted(false);
|
spec.setDeleted(false);
|
||||||
|
spec.setTags(List.of("search"));
|
||||||
|
spec.setCategories(List.of("halo"));
|
||||||
var excerpt = new Post.Excerpt();
|
var excerpt = new Post.Excerpt();
|
||||||
excerpt.setRaw("first post description");
|
excerpt.setRaw("first post description");
|
||||||
excerpt.setAutoGenerate(false);
|
excerpt.setAutoGenerate(false);
|
||||||
|
|
Loading…
Reference in New Issue