Skip to content

Part1 implement crud #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>

<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.3.1</version>
</dependency>

<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>

<build>
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/com/vincent/es/config/ElasticSearchConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.vincent.es.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.vincent.es.repository.StudentEsRepository;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticSearchConfig {

@Bean
public ElasticsearchClient elasticsearchClient() {
var httpHost = new HttpHost("localhost", 9200);
var restClient = RestClient.builder(httpHost).build();
var transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

return new ElasticsearchClient(transport);
}

@Bean
public StudentEsRepository studentEsRepository(ElasticsearchClient client) {
var repo = new StudentEsRepository(client, "student");
repo.init();
return repo;
}
}
52 changes: 52 additions & 0 deletions src/main/java/com/vincent/es/controller/StudentController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.vincent.es.controller;

import com.vincent.es.entity.Student;
import com.vincent.es.repository.StudentEsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping(value = "/students", produces = MediaType.APPLICATION_JSON_VALUE)
public class StudentController {

@Autowired
private StudentEsRepository studentEsRepository;

@PostMapping
public ResponseEntity<Student> create(@RequestBody Student request) {
var student = studentEsRepository.insert(request);
return ResponseEntity.status(HttpStatus.CREATED).body(student);
}

@PostMapping("/bulk")
public ResponseEntity<Void> create(@RequestBody List<Student> requests) {
studentEsRepository.insert(requests);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@PutMapping("/{id}")
public ResponseEntity<Void> update(@PathVariable("id") String id, @RequestBody Student request) {
request.setId(id);
studentEsRepository.save(request);
return ResponseEntity.noContent().build();
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable("id") String id) {
studentEsRepository.deleteById(id);
return ResponseEntity.noContent().build();
}

@GetMapping("/{id}")
public ResponseEntity<Student> get(@PathVariable("id") String id) {
var student = studentEsRepository.findById(id).orElse(null);
return student == null
? ResponseEntity.notFound().build()
: ResponseEntity.ok(student);
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/vincent/es/entity/Course.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.vincent.es.entity;

public class Course {
private String name; // 課程名稱
private int point; // 學分數

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getPoint() {
return point;
}

public void setPoint(int point) {
this.point = point;
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/vincent/es/entity/Job.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.vincent.es.entity;

public class Job {
private String name; // 職務名稱
private Boolean primary; // 是否主要 (正, 副)

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Boolean getPrimary() {
return primary;
}

public void setPrimary(Boolean primary) {
this.primary = primary;
}
}
106 changes: 106 additions & 0 deletions src/main/java/com/vincent/es/entity/Student.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.vincent.es.entity;

import java.util.Date;
import java.util.List;

public class Student {
private String id; // 學生編號,可當作 document id
private String name; // 姓名
private List<String> departments; // 科系
private List<Course> courses; // 修習課程
private int grade; // 年級
private int conductScore; // 操行成績
private Job job; // 職務
private String introduction; // 自我介紹
private Date englishIssuedDate; // 英文檢定通過日
private String bloodType; // 血型
private List<String> phoneNumbers; // 電話號碼

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<String> getDepartments() {
return departments;
}

public void setDepartments(List<String> departments) {
this.departments = departments;
}

public List<Course> getCourses() {
return courses;
}

public void setCourses(List<Course> courses) {
this.courses = courses;
}

public int getGrade() {
return grade;
}

public void setGrade(int grade) {
this.grade = grade;
}

public int getConductScore() {
return conductScore;
}

public void setConductScore(int conductScore) {
this.conductScore = conductScore;
}

public Job getJob() {
return job;
}

public void setJob(Job job) {
this.job = job;
}

public String getIntroduction() {
return introduction;
}

public void setIntroduction(String introduction) {
this.introduction = introduction;
}

public Date getEnglishIssuedDate() {
return englishIssuedDate;
}

public void setEnglishIssuedDate(Date englishIssuedDate) {
this.englishIssuedDate = englishIssuedDate;
}

public String getBloodType() {
return bloodType;
}

public void setBloodType(String bloodType) {
this.bloodType = bloodType;
}

public List<String> getPhoneNumbers() {
return phoneNumbers;
}

public void setPhoneNumbers(List<String> phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
}
138 changes: 138 additions & 0 deletions src/main/java/com/vincent/es/repository/StudentEsRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.vincent.es.repository;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.DateProperty;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import com.vincent.es.entity.Student;
import com.vincent.es.util.IOSupplier;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class StudentEsRepository {
private final ElasticsearchClient client;
private final String indexName;

public StudentEsRepository(ElasticsearchClient client, String indexName) {
this.client = client;
this.indexName = indexName;
}

public void init() {
deleteIndex();
createIndex();
}

public void createIndex() {
var propertyMap = getPropertyMappings();
var request = new CreateIndexRequest.Builder()
.index(indexName)
.mappings(TypeMapping.of(b -> b.properties(propertyMap)))
.build();

execute(() -> client.indices().create(request));
}

public void deleteIndex() {
var request = DeleteIndexRequest.of(b -> b.index(indexName));
execute(() -> client.indices().delete(request));
}

public Student insert(Student doc) {
var request = new CreateRequest.Builder<Student>()
.index(indexName)
.id(doc.getId())
.document(doc)
.build();

return execute(() -> {
var createResponse = client.create(request);
doc.setId(createResponse.id());
return doc;
});
}

public List<Student> insert(List<Student> docs) {
var builder = new BulkRequest.Builder().index(indexName);

docs.forEach(doc -> {
var createOp = new CreateOperation.Builder<Student>()
.id(doc.getId())
.document(doc)
.build();
var bulkOp = BulkOperation.of(b -> b.create(createOp));
builder.operations(bulkOp);
});

var bulkRequest = builder.build();

return execute(() -> {
var bulkResponse = client.bulk(bulkRequest);
List<BulkResponseItem> items = bulkResponse.items();
for (var i = 0; i < items.size(); i++) {
var id = items.get(i).id();
docs.get(i).setId(id);
}

return docs;
});
}

public Optional<Student> findById(String id) {
var request = new GetRequest.Builder()
.index(indexName)
.id(id)
.build();

var getResponse = execute(() -> client.get(request, Student.class));
return Optional.ofNullable(getResponse.source());
}

public Student save(Student doc) {
var request = new IndexRequest.Builder<Student>()
.index(indexName)
.id(doc.getId())
.document(doc)
.build();

return execute(() -> {
var indexResponse = client.index(request);
doc.setId(indexResponse.id());
return doc;
});
}

public void deleteById(String id) {
var request = new DeleteRequest.Builder()
.index(indexName)
.id(id)
.build();

execute(() -> client.delete(request));
}

private Map<String, Property> getPropertyMappings() {
var englishIssuedDateProperty = DateProperty.of(b -> b)._toProperty();
return Map.of("englishIssuedDate", englishIssuedDateProperty);
}

@SuppressWarnings({"squid:S112"})
private <V> V execute(IOSupplier<V> supplier) {
try {
return supplier.get();
} catch (IOException e) {
// 範例為求方便,只簡單做例外處理
throw new RuntimeException(e);
}
}

}
Loading