日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring elasticsearch 按条件删除_实战:项目数据源转为Elasticsearch

發布時間:2024/9/27 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring elasticsearch 按条件删除_实战:项目数据源转为Elasticsearch 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原本項目是基于MYSQL的,現因需求將其轉換為MYSQL+Elasticsearch,MYSQL的ORM使用的是Spring Data Jpa,Mybatis的轉換與其類似,有人看再更

先看原項目

原項目的DAO層

@Repository public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findOneByActivationKey(String activationKey);List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime);Optional<User> findOneByResetKey(String resetKey);Optional<User> findOneByEmailIgnoreCase(String email);Optional<User> findOneByLogin(String login);@EntityGraph(attributePaths = "authorities")Optional<User> findOneWithAuthoritiesById(Long id);@EntityGraph(attributePaths = "authorities")Optional<User> findOneWithAuthoritiesByLogin(String login);@EntityGraph(attributePaths = "authorities")Optional<User> findOneWithAuthoritiesByEmail(String email);Page<User> findAllByLoginNot(Pageable pageable, String login); }

原項目的DTO

1.User.java

@Entity @Table(name = "user") public class User implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@NotNull@Pattern(regexp = Constants.LOGIN_REGEX)@Size(min = 1, max = 50)@Column(length = 50, unique = true, nullable = false)private String login;@JsonIgnore@NotNull@Size(min = 60, max = 60)@Column(name = "password_hash", length = 60, nullable = false)private String password;@Email@Size(min = 5, max = 254)@Column(length = 254, unique = true)private String email;@NotNull@Column(nullable = false)private boolean activated = false;@Column(name = "reset_date")private Instant resetDate = null;@JsonIgnore@ManyToMany@JoinTable(name = "jhi_user_authority",joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")})@BatchSize(size = 20)private Set<Authority> authorities = new HashSet<>();//... }

2.Authority.java

@Entity @Table(name = "jhi_authority") public class Authority implements Serializable {private static final long serialVersionUID = 1L;@NotNull@Size(max = 50)@Id@Column(length = 50)private String name; }

可以看出原項目使用Spring data + hibernate 作為ORM,規范的使用其格式進行自動生成SQL語句


接下來就是轉換成elasticsearch的時候了

這里我不采用elasticsearch官網的client依賴包而是spring-data-elasticsearch,原因如下:

  • 官網提供的low包就是一個httpclient,做業務操作時需要自己編寫json,幾百個接口就要編寫幾百次json,過于麻煩
  • 官網提供的high包必須要與elasticsearch對應版本才行,不然項目就運行不起來
  • 原項目是使用Spring-data-jpa的,這里用spring-data-elasticsearch在更改時會方便很多
  • ①首先先配置elasticsearch

    pom.xml加入

    <dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-elasticsearch</artifactId></dependency>

    若你是spring boot項目,則在 application.yml 或者 application.properties 加入

    spring: data:elasticsearch:cluster-nodes: localhost:9300

    若你是普通spring項目則看

    Spring Data Elasticsearch?docs.spring.io

    進行配置

    ②改造DTO

    把原有的spring data 注解刪除掉

    然后替換成elasticsearch的注解

    @Document(indexName = "user", type = "doc") public class User {//這里的instant jackson無法直接從string轉換為instant,需要編寫個編解碼類@JsonSerialize(using = InstantJacksonSerializer.class)@JsonDeserialize(using = InstantJacksonDeserialize.class)private Instant createdDate;private String createdBy;private boolean activated;//原項目Id,是使用Long類型,這里不改,但elasticsearch的話推薦使用String作為Id,因為自動創建id的時候為隨機字符串@Idprivate Long id;private Set<Authority> authorities;private String login;private String email;//... }

    可以看到,我除了刪除了原項目的注解外,DTO就只有添加了 @Document(indexName = user", type = "doc") ,Instant是原項目使用的,如果是用Date的話則使用 @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")

    ③改造DAO層

    先看改造后的

    public interface UserRepository extends ElasticsearchRepository<User, Long> {Optional<User> findOneByActivationKey(String activationKey);List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime);Optional<User> findOneByResetKey(String resetKey);Optional<User> findOneByEmailIgnoreCase(String email);Optional<User> findOneByLogin(String login);Optional<User> findOneByEmail(String email);Page<User> findAllByLoginNot(Pageable pageable, String login);}

    將UserRepository 改為繼承ElasticsearchRepository<User, Long> ,其中第一個參數為DTO,第二個參數為Id,把連表的with給去掉即可(IDEA中用shift+F6可以很方便的),若你需要特殊查詢,可以使用

    @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")Page<Book> findByName(String name,Pageable pageable);

    ④關于join的問題

    Elasticsearch是不支持join操作的,可以有以下幾種解決方案

  • 因SQL不支持數組才把其放入其他表的,Elasticsearch本身支持數組,直接放入同一張表
  • 一對多,一對一,多對一情況下的,可以考慮數據冗余,直接加入同一張表中,Elasticsearch本身儲存的數據會進行壓縮的,數據冗余可以接受,在不加索引情況下可能達到MYSQL十分之一的存儲空間
  • 使用父子關系(不推薦,之前看到好像在將來的版本會被廢棄?)
  • 兩次查詢解決join問題(實在沒辦法了就只能這樣做了)
  • 在本項目中我用的是方案一,再復雜點的情況之后再考慮

    ⑤關于遇到的坑

    //MYSQL@Size(max = 50)@Column(name = "first_name", length = 50)private String firstName;//Elasticsearchprivate String firstName;

    MYSQL數據庫里儲存的字段名都是first_name這樣以下劃線作為分詞的,而spring data Elasticsearch 我并沒有找到轉義的相應注解。。。。如果有人知道麻煩告訴下

    我的解決方案:

    在導入數據源的時候,把其改為駝峰法的結構

    ⑥數據導入

    我使用的是logstash,還有其他框架可以使用,按需求自己決定吧

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的spring elasticsearch 按条件删除_实战:项目数据源转为Elasticsearch的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。