基于Spring Boot+Elasticsearch实现类谷歌搜索引擎,需按_source字段搜索
Hey there! Let's get that _source-based search up and running for your Spring Boot + Elasticsearch search engine. Since you already have the index set up via Logstash and can fetch records by ID, here's a straightforward implementation tailored to your setup:
First, create an entity class that maps directly to the _source fields in your bookdata index. This lets Spring Data Elasticsearch handle serialization/deserialization of search results seamlessly:
import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; // For Elasticsearch 7.x+, remove the `type` parameter (it's deprecated) @Document(indexName = "bookdata", type = "books") public class Book { @Id private String id; private String title; private String author; private String description; // Add other fields that match your _source structure // Include getters and setters for all fields }
Next, create a service class to construct and execute Elasticsearch queries. We'll use a multi-match query here to search across multiple fields in the _source (adjust the field names to match your actual data):
import org.elasticsearch.index.query.QueryBuilders; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; @Service public class BookSearchService { private final String INDEX = "bookdata"; private final String TYPE = "books"; // Remove this for ES 7.x+ private final ElasticsearchRestTemplate elasticsearchRestTemplate; // Constructor injection (preferred over @Autowired) public BookSearchService(ElasticsearchRestTemplate elasticsearchRestTemplate) { this.elasticsearchRestTemplate = elasticsearchRestTemplate; } public SearchHits<Book> searchBooksByKeyword(String keyword) { // Build a multi-match query to search across title, author, and description NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withIndices(INDEX) .withTypes(TYPE) // Remove this line for ES 7.x+ .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "author", "description") .fuzziness("AUTO") // Handle minor spelling errors .prefixLength(2)) // Optimize performance for prefix matches .build(); return elasticsearchRestTemplate.search(searchQuery, Book.class); } }
Expose an endpoint so your search component can send requests and receive results:
import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class BookSearchController { private final BookSearchService bookSearchService; public BookSearchController(BookSearchService bookSearchService) { this.bookSearchService = bookSearchService; } @GetMapping("/search") public SearchHits<Book> searchBooks(@RequestParam String keyword) { return bookSearchService.searchBooksByKeyword(keyword); } }
Highlight Matching Text: Show users exactly where their keyword appears by adding highlighting to the query. Modify the service method like this:
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withIndices(INDEX) .withTypes(TYPE) .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "author", "description")) .withHighlightFields( new HighlightBuilder.Field("title").preTags("<strong>").postTags("</strong>"), new HighlightBuilder.Field("description").preTags("<strong>").postTags("</strong>") ) .build();You can retrieve the highlighted content from
SearchHitobjects later to display in your frontend.Precise Phrase Matching: If you want to match exact phrases instead of individual words, use
QueryBuilders.matchPhraseQuery("title", keyword)instead of the multi-match query.
内容的提问来源于stack exchange,提问作者Karthikeyan

