Erweiterte Anwendungsbeispiele für Spring Data Elasticsearch

Such-/Filterfunktion

1. Volltextsuche

Spring Data Elasticsearch unterstützt die Volltextsuchfunktion, die das Auffinden von Schlüsselwörtern in Textdaten sehr einfach macht. Wir können die Annotation @Field verwenden, um das Textfeld anzugeben, und die Volltextsuchabfrage verwenden, um den Suchvorgang durchzuführen.

@Field(type = FieldType.Text, analyzer = "standard")
private String title;

2. Aggregation

Die leistungsstarke Aggregationsfunktion von Elasticsearch ermöglicht uns die Durchführung von Statistiken, Analysen und Zusammenfassungen von Daten. Spring Data Elasticsearch bietet aggregationsbezogene APIs, damit wir verschiedene Analysevorgänge durchführen können.

AggregationBuilder aggregation = AggregationBuilders
    .terms("genreAgg")
    .field("genre.keyword")
    .size(10);

SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .addAggregation(aggregation)
    .build();

Aggregations aggregations = elasticsearchRestTemplate.query(searchQuery,
    response -> response.getAggregations());

3. Filtern

Mit Spring Data Elasticsearch können wir verschiedene Filtervorgänge durchführen, um Dokumente herauszufiltern, die bestimmten Kriterien entsprechen. Dies kann uns helfen, die Teilmenge der interessierenden Daten zu extrahieren.

Criteria criteria = Criteria.where("genre").is("Fiction");
FilterQuery filterQuery = new SimpleFilterQuery(criteria);

SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(matchAllQuery())
    .withFilter(filterQuery)
    .build();

List<Book> filteredBooks = elasticsearchRestTemplate.queryForList(searchQuery, Book.class);

Während wir unseren Blogbeitrag fortsetzen, wollen wir uns mit einigen fortgeschritteneren Themen befassen, um den Lesern zu einem umfassenderen Verständnis von Spring Data Elasticsearch zu verhelfen.

Andere Eigenschaften

1. Markieren Sie Suchergebnisse

Das Hervorheben von Ergebnissen, die einer Suchanfrage entsprechen, ist in Suchanwendungen häufig eine nützliche Funktion. Mit Spring Data Elasticsearch können wir passenden Text in Abfrageergebnissen hervorheben.

HighlightBuilder.Field highlightField = new HighlightBuilder.Field("title");
highlightField.preTags("<em>");
highlightField.postTags("</em>");

NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(QueryBuilders.matchQuery("title", "spring framework"))
    .withHighlightFields(highlightField)
    .build();

SearchHits<Book> searchHits = elasticsearchRestTemplate.search(searchQuery, Book.class, IndexCoordinates.of("books"));

// 提取高亮信息
for (SearchHit<Book> searchHit : searchHits) {
    
    
    List<String> highlightSnippets = searchHit.getHighlightField("title");
    // 处理高亮信息
}

2. Geolokalisierungssuche

Elasticsearch verfügt über eine leistungsstarke Suchfunktion für geografische Standorte, mit der wir Dokumente anhand geografischer Koordinaten abfragen können. Spring Data Elasticsearch unterstützt auch Geolocation-Abfragen.

GeoPoint location = new GeoPoint(40.7128, -74.0060);
GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location")
    .point(location)
    .distance(50, DistanceUnit.KILOMETERS);

NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(queryBuilder)
    .build();

SearchHits<Place> searchHits = elasticsearchRestTemplate.search(searchQuery, Place.class);

3. Benutzerdefinierter Analysator

Wenn wir den Textanalyseprozess anpassen müssen, um ihn besser an unsere Daten anzupassen, können wir mit Spring Data Elasticsearch benutzerdefinierte Analysetools definieren und verwenden.

@Setting(settingPath = "custom-analysis.json")
public class Book {
    
    
    // ...
}

In diesem Beispiel haben wir über die Annotation @Setting auf eine benutzerdefinierte Analysekonfigurationsdatei mit dem Namencustom-analysis.json verwiesen.

Anwendungsfälle

Lassen Sie uns die Leistungsfähigkeit von Spring Data Elasticsearch anhand eines praktischen Anwendungsfalls demonstrieren.

Fall: Geolokalisierungssuche

Nehmen wir an, wir entwickeln eine Restaurant-Finder-Anwendung. Benutzer können einen Ort auf der Karte auswählen und nach Restaurants in der Nähe suchen. Dies ist ein typischer Anwendungsfall für die Geolokalisierungssuche.

@GetMapping("/restaurants")
public List<Restaurant> searchRestaurants(@RequestParam double latitude, @RequestParam double longitude) {
    
    
    GeoPoint location = new GeoPoint(latitude, longitude);
    GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location")
        .point(location)
        .distance(5, DistanceUnit.KILOMETERS);

    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withQuery(queryBuilder)
        .build();

    SearchHits<Restaurant> searchHits = elasticsearchRestTemplate.search(searchQuery, Restaurant.class);

    // 返回附近的餐厅列表
    return searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

In diesem Fall sucht der Benutzer nach nahegelegenen Restaurants, indem er Längen- und Breitengradkoordinaten angibt. Mit Spring Data Elasticsearch können wir solche Geolocation-Abfragen einfach durchführen.

4. Benutzerdefinierte Abfrage

Mit Spring Data Elasticsearch können wir benutzerdefinierte Abfragemethoden definieren, um erweiterte Abfragen basierend auf spezifischen Anforderungen durchzuführen. Dies kann durch die Erstellung von Schnittstellenmethoden und die Verwendung von @Query-Annotationen erreicht werden.

@Query("{\"match\": {\"title\": \"?0\"}}")
List<Book> findByTitle(String title);

In diesem Beispiel erstellen wir eine benutzerdefinierte Abfragemethode und geben die JSON-Zeichenfolge der Abfrage über die Annotation @Query an. Dadurch können wir komplexere Abfragen wie Volltextsuchen oder Fuzzy-Matching durchführen.

5. Verwenden von Spring's Page and Sort

Spring Data Elasticsearch unterstützt auch Page- und Sort-Objekte, was das Paginieren und Sortieren vereinfacht. Wir können diese Objekte in Abfragemethoden verwenden, um Paging und Sortierung von Ergebnissen zu implementieren.

Page<Book> findByGenre(String genre, Pageable pageable);

In diesem Beispiel verwenden wir das Pageable-Objekt, um die Paging-Abfrage nach dem genre-Feld zu implementieren.

6. Skriptabfrage

Elasticsearch ermöglicht uns die Verwendung von Skripten zur Durchführung komplexer Abfragen und Datentransformationen. Spring Data Elasticsearch unterstützt skriptbasierte Abfragen über @ScriptedField-Annotationen.

@ScriptedField(name = "discountedPrice", script = "doc['price'].value * 0.9")
private Double discountedPrice;

In diesem Beispiel verwenden wir die Annotation @ScriptedField, um ein berechnetes Feld mit dem Namen discountedPrice basierend auf pricedem Wert zu erstellen des Feldes berechnet den Rabattpreis.

7. Multi-Index-Abfrage

Wenn unsere Daten auf mehrere Indizes verteilt sind, unterstützt Spring Data Elasticsearch auch Multi-Index-Abfragen. Wir können IndexCoordinates verwenden, um mehrere Indizes anzugeben.

IndexCoordinates index1 = IndexCoordinates.of("index1");
IndexCoordinates index2 = IndexCoordinates.of("index2");

SearchHits<Book> searchHits = elasticsearchRestTemplate.search(query, Book.class, index1, index2);

Fall: Multi-Index-Abfrage

Angenommen, wir entwickeln eine Anwendung zur Nachrichtenaggregation, bei der Nachrichtendaten in verschiedenen Indizes gespeichert werden, wobei jeder Index einer anderen Nachrichtenquelle entspricht. Wir können die Multi-Index-Abfrage von Spring Data Elasticsearch verwenden, um Nachrichtendaten über mehrere Indizes hinweg abzurufen.

IndexCoordinates index1 = IndexCoordinates.of("news_source1");
IndexCoordinates index2 = IndexCoordinates.of("news_source2");

NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(QueryBuilders.matchAllQuery())
    .build();

SearchHits<NewsArticle> searchHits = elasticsearchRestTemplate.search(searchQuery, NewsArticle.class, index1, index2);

// 返回跨多个索引的新闻数据
List<NewsArticle> newsArticles = searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());

In diesem Fall haben wir zwei verschiedeneIndexCoordinatess verwendet, um Abfragen über mehrere Indizes hinweg durchzuführen.

8. Mehrsprachige Unterstützung

Wenn unsere Anwendung die Volltextsuche in mehreren Sprachen unterstützen muss, stellt Elasticsearch mehrsprachige Analysatoren und Filter bereit. Mit Spring Data Elasticsearch können wir verschiedene Analysatoren für verschiedene Bereiche verwenden.

@Field(type = FieldType.Text, analyzer = "english_analyzer")
private String title;

@Field(type = FieldType.Text, analyzer = "chinese_analyzer")
private String content;

In diesem Beispiel verwenden wir den englischen Analysator für das Feld title und den chinesischen Analysator für das Feld content, um mehrsprachige Suchen zu ermöglichen.

Fall: Unterstützung mehrerer Sprachen

Angenommen, wir entwickeln ein mehrsprachiges Nachrichtenportal, in dem Nachrichtenartikel in verschiedenen Sprachen verfasst werden können. Wir können die Mehrsprachenunterstützung von Spring Data Elasticsearch nutzen, um eine Volltextsuche zu implementieren.

@Field(type = FieldType.Text, analyzer = "english_analyzer")
private String title;

@Field(type = FieldType.Text, analyzer = "french_analyzer")
private String content;

@Field(type = FieldType.Text, analyzer = "german_analyzer")
private String description;

In diesem Fall verwenden wir den englischen Parser für das Feld title, den französischen Parser für das Feld content und den französischen Parser für das Feld < /span>descriptionField verwendet den deutschen Analysator, um die mehrsprachige Suche zu unterstützen.

9. Verbindungspoolverwaltung

In einer Produktionsumgebung ist es sehr wichtig, den Verbindungspool richtig zu konfigurieren, um eine effiziente Nutzung von Elasticsearch-Verbindungen sicherzustellen. Spring Data Elasticsearch bietet einige Konfigurationsoptionen zum Verwalten von Verbindungspools.

propertiesCopy codespring.data.elasticsearch.properties.http.max_connections=100
spring.data.elasticsearch.properties.http.max_connections_per_route=10

Durch die Konfigurationmax_connections und max_connections_per_route können wir die Größe des Verbindungspools steuern.

10. Versionskontrolle des Dokuments

In verteilten Systemen ist die Versionskontrolle von Dokumenten sehr wichtig, um Datenkonflikte und -verluste zu vermeiden. Elasticsearch bietet einen Mechanismus zur Dokumentversionskontrolle, der eine Dokumentversionsverwaltung durch @Version Kommentare und @SeqNoPrimaryTerm Kommentare erreichen kann.

@Version
private Long version;

@SeqNoPrimaryTerm
private SeqNoPrimaryTerm seqNoPrimaryTerm;

Mithilfe dieser Anmerkungen können wir die Version und Seriennummer eines Dokuments verfolgen, um Konflikte bei gleichzeitigen Vorgängen ordnungsgemäß zu lösen.

11. Suchvorschläge

Die Implementierung einer Suchvorschlagsfunktion ist eine Möglichkeit, das Benutzererlebnis zu verbessern, indem Benutzern in Echtzeit Vorschläge gemacht werden, während sie ihre Suchanfrage eingeben. Mit Spring Data Elasticsearch können wir Suchvorschlagsabfragen durchführen, um Vorschläge basierend auf Benutzereingaben bereitzustellen.

@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

public List<String> suggestTerms(String input) {
    
    
    CompletionSuggestionBuilder suggestionBuilder = SuggestBuilders.completionSuggestion("suggest")
        .prefix(input)
        .size(5);

    SuggestBuilder suggest = new SuggestBuilder().addSuggestion("suggest-terms", suggestionBuilder);

    SearchResponse searchResponse = elasticsearchRestTemplate.suggest(suggest, Book.class);
    Suggest suggestResult = searchResponse.getSuggest();

    if (suggestResult != null) {
    
    
        List<Suggest.Suggestion.Entry.Option> options = suggestResult.getSuggestion("suggest-terms").getEntries().get(0).getOptions();
        return options.stream().map(Suggest.Suggestion.Entry.Option::getText).collect(Collectors.toList());
    } else {
    
    
        return Collections.emptyList();
    }
}

In diesem Beispiel haben wirCompletionSuggestionBuilder verwendet, um eine Vorschlagsabfrage durchzuführen und Vorschläge zurückzugeben, die der Eingabe des Benutzers entsprechen.

Fall: Suchvorschläge

Nehmen wir an, wir entwickeln eine E-Commerce-Website und möchten den Benutzern Suchvorschläge bereitstellen, damit sie die gesuchten Produkte leichter finden können. Dies können wir mithilfe der Suchvorschlagsfunktion von Spring Data Elasticsearch erreichen.

@GetMapping("/suggest")
public List<String> suggestProducts(@RequestParam String query) {
    
    
    return productService.suggestTerms(query);
}

In diesem Fall wird die vom Benutzer eingegebene Suchanfrage verwendet, um Suchvorschläge zu erhalten, die ihm bei der Suche nach relevanten Produkten helfen.

Großer Koffer für eine E-Commerce-Plattform

Fallhintergrund

Angenommen, es gibt ein globales E-Commerce-Unternehmen. Es ist in mehreren Ländern und Regionen tätig und verfügt über einen riesigen Produktkatalog, Millionen von Benutzern und Tausende gleichzeitiger Online-Transaktionen. Um ein so großes Geschäft abzuwickeln, verlassen sie sich auf Elasticsearch als Such- und Produktempfehlungsmaschine.

Fall Analyse

Bei dieser groß angelegten E-Commerce-Plattform spielt Spring Data Elasticsearch eine Schlüsselrolle:

  1. Volltextsuche: Nutzer können die Suchmaschine nutzen, um Produkte schnell zu finden. Mit Spring Data Elasticsearch wird eine leistungsstarke Volltextsuchmaschine erstellt, die Funktionen wie die automatische Korrektur von Rechtschreibfehlern, die Empfehlung verwandter Suchbegriffe und Suchvorschläge unterstützt.
  2. Produktempfehlung: Die Plattform nutzt den Browser- und Kaufverlauf der Nutzer sowie Empfehlungsalgorithmen wie kollaborative Filterung, um Nutzern personalisierte Produktempfehlungen zu geben. Spring Data Elasticsearch wird zum Speichern und Abrufen von Produkt- und Benutzerverhaltensdaten verwendet.
  3. Bestands- und Preisaktualisierungen in Echtzeit: E-Commerce-Plattformen müssen den Bestandsstatus und den Preis von Waren zeitnah aktualisieren. Die Echtzeit-Indexaktualisierungsfunktion von Spring Data Elasticsearch gewährleistet die zeitnahe Verfügbarkeit von Daten.
  4. Länderübergreifende internationale Suche: Aufgrund des länderübergreifenden Betriebs können Benutzer in mehreren Sprachen nach Produkten suchen. Spring Data Elasticsearch unterstützt die mehrsprachige Volltextsuche und stellt lokalisierte Suchergebnisse basierend auf dem Standort des Benutzers bereit.
  5. Überwachung und Leistungsoptimierung: Die E-Commerce-Plattform muss die Leistung und den Zustand des Elasticsearch-Clusters regelmäßig überwachen und eine Leistungsoptimierung durchführen. Spring Data Elasticsearch integriert Überwachungstools und Leistungsanalyse-Plugins, um diese Ziele zu erreichen.
  6. Auftragsverfolgung: Benutzer können den Status ihrer Bestellungen in Echtzeit verfolgen. Spring Data Elasticsearch wird zum Speichern und Abrufen von Bestelldaten verwendet, um schnelle und Echtzeit-Auftragsverfolgungsdienste bereitzustellen.

Architektur-Design

In der Architektur dieser E-Commerce-Plattform umfassen Elasticsearch-Cluster normalerweise mehrere Knoten, um Hochverfügbarkeit und horizontale Erweiterung zu unterstützen. Spring Data Elasticsearch wird mit Spring Boot verwendet, um über eine RESTful-API mit dem Elasticsearch-Cluster zu kommunizieren. Darüber hinaus kann die Plattform auch andere Technologie-Stacks wie Redis-Caching, Nachrichtenwarteschlangen usw. nutzen, um Leistung und Skalierbarkeit zu verbessern.

Projektherausforderungen

Bei einer so großen E-Commerce-Plattform steht die Verwendung von Spring Data Elasticsearch vor den folgenden Herausforderungen:

  • Hohe Auslastung und Parallelität: Die Verarbeitung hoher Auslastung und gleichzeitiger Anfragen von Millionen von Benutzern erfordert hochoptimierte Suchmaschinen und Datenspeicher.
  • Datenkonsistenz: Die Sicherstellung der Konsistenz von Produktbestands-, Preis- und Bestelldaten ist ein komplexes Thema, das einen effektiven Synchronisierungsmechanismus erfordert.
  • Echtzeitanforderungen: Echtzeitaktualisierungen von Bestands- und Preisinformationen erfordern schnelle Indexaktualisierungen.
  • Mehrsprachigkeit und Lokalisierung: Die Unterstützung mehrsprachiger Suchen und die Bereitstellung lokalisierter Ergebnisse erfordert eine detaillierte Konfiguration und Verarbeitung.
  • Überwachung und Wartung: Die Überwachung des Zustands und der Leistung großer Elasticsearch-Cluster erfordert spezielle Tools und Vorgehensweisen.

Codebeispiel

Für große Projekte kann ich hier nicht den vollständigen Code bereitstellen, da solche Projekte meist sehr komplex sind und eine Vielzahl an Codedateien und Abhängigkeiten enthalten. Ich habe es zu einem logischen Beispiel vereinfacht, das zeigt, wie man mit Spring Data Elasticsearch grundlegende Volltextsuch- und Speichervorgänge durchführt.

Stellen Sie zunächst sicher, dass unser Spring Boot-Projekt ordnungsgemäß eingerichtet ist und die Spring Data Elasticsearch-Abhängigkeit enthält.

Projektstruktur

Erstellen wir zunächst die Projektstruktur:

cssCopy codemy-ecommerce-project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   ├── com/
│   │   │   │   ├── example/
│   │   │   │   │   ├── controller/
│   │   │   │   │   │   ├── ProductController.java
│   │   │   │   │   │   ├── UserController.java
│   │   │   │   │   ├── model/
│   │   │   │   │   │   ├── Product.java
│   │   │   │   │   │   ├── User.java
│   │   │   │   │   ├── repository/
│   │   │   │   │   │   ├── ProductRepository.java
│   │   │   │   │   │   ├── UserRepository.java
│   │   │   │   │   ├── service/
│   │   │   │   │   │   ├── ProductService.java
│   │   │   │   │   │   ├── UserService.java
│   ├── resources/
│   │   ├── application.properties

Entitätsklasse

Erstellen SieProduct und User Entitätsklassen, um Produkte bzw. Benutzer darzustellen:

// Product.java
@Entity
@Document(indexName = "products")
public class Product {
    
    
    @Id
    private String id;
    private String name;
    private double price;
    
    // 省略构造函数、getter和setter
}

// User.java
@Entity
@Document(indexName = "users")
public class User {
    
    
    @Id
    private String id;
    private String username;
    
    // 省略构造函数、getter和setter
}

Repository-Schnittstelle

ErstellenProductRepository und UserRepository Schnittstellen zum Ausführen von CRUD-Operationen:

public interface ProductRepository extends ElasticsearchRepository<Product, String> {
    
    
    List<Product> findByNameContaining(String name);
}

public interface UserRepository extends ElasticsearchRepository<User, String> {
    
    
    Optional<User> findByUsername(String username);
}

Serviceklasse

Erstellen SieProductService und UserService Klassen zum Ausführen von Geschäftslogik:

@Service
public class ProductService {
    
    
    @Autowired
    private ProductRepository productRepository;

    public void saveProduct(Product product) {
    
    
        productRepository.save(product);
    }

    public List<Product> searchProductsByName(String name) {
    
    
        return productRepository.findByNameContaining(name);
    }
}

@Service
public class UserService {
    
    
    @Autowired
    private UserRepository userRepository;

    public void saveUser(User user) {
    
    
        userRepository.save(user);
    }

    public Optional<User> findUserByUsername(String username) {
    
    
        return userRepository.findByUsername(username);
    }
}

Regler

Erstellen SieProductController und UserController Controller zur Verarbeitung von HTTP-Anfragen:

@RestController
@RequestMapping("/products")
public class ProductController {
    
    
    @Autowired
    private ProductService productService;

    @PostMapping
    public ResponseEntity<?> addProduct(@RequestBody Product product) {
    
    
        productService.saveProduct(product);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/search")
    public ResponseEntity<List<Product>> searchProducts(@RequestParam String query) {
    
    
        List<Product> products = productService.searchProductsByName(query);
        return ResponseEntity.ok(products);
    }
}

@RestController
@RequestMapping("/users")
public class UserController {
    
    
    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<?> addUser(@RequestBody User user) {
    
    
        userService.saveUser(user);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/search")
    public ResponseEntity<User> searchUser(@RequestParam String username) {
    
    
        Optional<User> user = userService.findUserByUsername(username);
        return user.map(ResponseEntity::ok)
                   .orElse(ResponseEntity.notFound().build());
    }
}

Hauptklasse der Anwendung

Fügen Sie in der Hauptklasse Ihrer Spring Boot-Anwendung die folgenden Anmerkungen hinzu, um die automatische Konfiguration des Elasticsearch-Warehouses zu ermöglichen und die Elasticsearch-Verbindung zu konfigurieren:

@SpringBootApplication
@EnableElasticsearchRepositories(basePackages = "com.example.repository")
public class MyElasticsearchApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(MyElasticsearchApplication.class, args);
    }
}

Dieses Beispielprojekt enthält mehr Geschäftslogik und Funktionalität, einschließlich Logik für Produktverwaltung, Benutzersuche und Auftragsabwicklung. Wir können es entsprechend den Anforderungen des Projekts weiter erweitern, indem wir weitere Entitätsklassen, benutzerdefinierte Abfragen, Sicherheit, Leistungsoptimierung und -überwachung usw. hinzufügen. Hoffentlich erfüllt dieses Beispiel unsere Anforderungen und bietet detailliertere Beispiele für Spring Data Elasticsearch.

Guess you like

Origin blog.csdn.net/weixin_45525272/article/details/133744632