基于Hibernate Search与ElasticSearch的搜索引擎实现示例代码需求
Got it, let's build your search suggestion feature step by step. I'll break this down into concrete, actionable code examples that fit your tech stack.
1. Project Dependencies (Maven)
First, add these dependencies to your pom.xml to pull in all the required libraries:
<dependencies> <!-- Spring Boot Web for REST endpoints --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Oracle JDBC Driver --> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <scope>runtime</scope> </dependency> <!-- Hibernate Core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.32.Final</version> </dependency> <!-- Hibernate Search ORM --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.9.1.Final</version> </dependency> <!-- Hibernate Search Elasticsearch Integration --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-elasticsearch</artifactId> <version>5.9.1.Final</version> </dependency> </dependencies>
2. Annotated Entity Class (Indexed for Search)
Let's create a sample entity (e.g., WebDocument) that maps to your Oracle table and is marked for indexing with Hibernate Search:
import javax.persistence.*; import org.hibernate.search.annotations.*; @Entity @Table(name = "WEB_DOCUMENTS") // Match your actual Oracle table name @Indexed(index = "web_documents") // Name of the Elasticsearch index @AnalyzerDef(name = "customAnalyzer", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), filters = { @TokenFilterDef(factory = LowerCaseFilterFactory.class), @TokenFilterDef(factory = StopFilterFactory.class) } ) public class WebDocument { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "doc_seq") @SequenceGenerator(name = "doc_seq", sequenceName = "WEB_DOCUMENTS_SEQ", allocationSize = 1) private Long id; @Field(analyzer = @Analyzer(definition = "customAnalyzer")) @Column(name = "TITLE") private String title; @Field(analyzer = @Analyzer(definition = "customAnalyzer")) @Column(name = "CONTENT") private String content; // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
3. Application Configuration (application.properties)
Configure your Oracle connection and Hibernate Search Elasticsearch settings here:
# Oracle Database Configuration spring.datasource.url=jdbc:oracle:thin:@//your-oracle-host:1521/your-service-name spring.datasource.username=your-db-username spring.datasource.password=your-db-password spring.datasource.driver-class-name=oracle.jdbc.OracleDriver # Hibernate Configuration spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect # Hibernate Search Elasticsearch Configuration hibernate.search.default.directory_provider=elasticsearch hibernate.search.default.elasticsearch.host=http://localhost:9200 hibernate.search.default.elasticsearch.index_schema_management_strategy=CREATE hibernate.search.default.elasticsearch.refresh_after_write=true
4. Search Service Implementation
Create a service class to handle the search suggestion logic:
import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.Search; import org.hibernate.search.query.dsl.QueryBuilder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.List; @Service @Transactional public class SearchService { @PersistenceContext private EntityManager entityManager; public List<WebDocument> getSearchSuggestions(String keyword) { FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); // Build a query builder tailored to our entity QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory() .buildQueryBuilder() .forEntity(WebDocument.class) .get(); // Create a wildcard query to match terms starting with the input keyword org.apache.lucene.search.Query luceneQuery = queryBuilder .keyword() .wildcard() .onFields("title", "content") .matching(keyword + "*") .createQuery(); // Wrap the Lucene query in a JPA-compatible query javax.persistence.Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, WebDocument.class); // Return top 10 suggestions (adjust this number as needed) return jpaQuery.setMaxResults(10).getResultList(); } }
5. REST Controller
Expose the search suggestion functionality via a REST endpoint:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class SearchController { @Autowired private SearchService searchService; @GetMapping("/api/search/suggest") public List<WebDocument> getSuggestions(@RequestParam("keyword") String keyword) { return searchService.getSearchSuggestions(keyword); } }
6. Initialize Index (Optional)
If you already have existing data in your Oracle table, add this component to trigger indexing on app startup:
import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.Search; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Component public class IndexInitializer { @PersistenceContext private EntityManager entityManager; @EventListener(ApplicationReadyEvent.class) @Transactional public void initializeIndex() { FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); try { fullTextEntityManager.createIndexer().startAndWait(); System.out.println("Elasticsearch index initialized successfully!"); } catch (InterruptedException e) { System.err.println("Error initializing index: " + e.getMessage()); Thread.currentThread().interrupt(); } } }
Testing the Endpoint
Run your Spring Boot app, then send a GET request to:http://localhost:8080/api/search/suggest?keyword=xyz
You'll get a JSON response with the top 10 documents where the title or content starts with "xyz".
内容的提问来源于stack exchange,提问作者Karthikeyan

