Springboot: Каков наилучший способ поиска списка сущностей, используя более чем одну из его характеристик - PullRequest
0 голосов
/ 15 мая 2018

Я разрабатываю веб-приложение в Spring-boot, где пользователь может искать пользователей, используя поле поиска.Запрашиваемые пользователи (которые зависят от значения, введенного в поле ввода) будут опрошены в соответствии с их именем пользователя, именем и фамилией.Это моя UserModel:

    @Component
@Entity
@Table(name = "Users")
public class User extends DefaultEntity {


    @Column(name = "FirstName")
    @NotNull(message = "Enter a FirstName")
    private String firstName;


    @Column(name = "LastName")
    @NotBlank(message = "Enter a LastName")
    private String lastName;


    @Column(unique = true,name = "UserName")
    @NotBlank(message = "Enter a UserName")
    private String userName;


    @Column(unique = true, name = "Email")
    @NotBlank(message = "Please enter an Email address")
    @Email(message = "Enter a valid Email")
    private String email;


    @Column(name = "Password")
    @NotBlank(message = "Enter a Password")
    private String password;


    @Enumerated(EnumType.STRING)
    @Column(name = "Gender")
    private Gender gender;


    @Column(name = "Address")
    @NotBlank(message = "Please enter your Home Address")
    private String address;


    @Column(name = "Country")
    @NotBlank(message = "Please enter your Country")
    private String country;


    @Column(name = "Picture")
    private String picture;


    @Column(unique = true, name = "PhoneNumber") //make this accept only numbers
    private String phoneNumber;


    @Column(name = "Bio")
    private String bio;


    @Enumerated(EnumType.STRING)
    @Column(name = "OnlineStatus")
    private OnlineStatus onlineStatus;

    @Enumerated(EnumType.STRING)
    @Column(name = "UserType")
    private UserType userType;


    @Column(name = "Money")
    private double money;


    //@MapsId()
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "playerstats")
    private PlayerStats playerStats;

    //columnDefinition = "tinyint default false"
    @Column(name = "locked",columnDefinition = "BOOL default false")
    private Boolean locked;



    @Transient
    private MultipartFile file;


    public String getFirstName() {
        return firstName;
    }

    public User setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }

    public String getLastName() {
        return lastName;
    }

    public User setLastName(String lastName) {
        this.lastName = lastName;
        return this;
    }

    public String getUserName() {
        return userName;
    }

    public User setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getEmail() {
        return email;
    }

    public User setEmail(String email) {
        this.email = email;
        return this;
    }

    public String getPassword() {
        return password;
    }

    public User setPassword(String password) {
        this.password = password;
        return this;
    }

    public Enum.Gender getGender() {
        return gender;
    }

    public User setGender(Enum.Gender gender) {
        this.gender = gender;
        return this;
    }

    public String getAddress() {
       return address;
    }

    public User setAddress(String address) {
       this.address = address;
       return this;
    }

    public String getCountry() {
        return country;
    }

    public User setCountry(String country) {
        this.country = country;
        return this;
    }

    public String getPicture() {
        return picture;
    }

    public User setPicture(String picture) {
        this.picture = picture;
        return this;
    }

    public String getBio() {
        return bio;
    }

    public User setBio(String bio) {
        this.bio = bio;
        return this;
    }

    public Enum.OnlineStatus getOnlineStatus() {
        return onlineStatus;
    }

    public User setOnlineStatus(Enum.OnlineStatus onlineStatus) {
        this.onlineStatus = onlineStatus;
        return this;
    }

    public Enum.UserType getUserType() {
        return userType;
    }

    public User setUserType(Enum.UserType userType) {
        this.userType = userType;
        return this;
    }

    public double getMoney() {
        return money;
    }

    public User setMoney(double money) {
        this.money = money;
        return this;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public User setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
        return this;
    }

    public MultipartFile getFile() {
        return file;
    }

    public User setFile(MultipartFile file) {
        this.file = file;
        return this;
    }

    public PlayerStats getPlayerStats() {
        return playerStats;
    }

    public User setPlayerStats(PlayerStats playerStats) {
        this.playerStats = playerStats;
        return this;
    }

    public Boolean getLocked() {
        return locked;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

}

Это мой метод запроса usermodel в моем UserRepository:

    @Repository
public interface UserRepository extends JpaRepository<User,Long> {


    Page<User> findUsersByUserNameContainingOrFirstNameContainingOrLastNameContaining(String UserName, String FirstName, String LastName, Pageable pageable);

}

Мой вопрос: есть ли лучший способ или более эффективный способ выполнения запросовпользовательский объект?

1 Ответ

0 голосов
/ 16 мая 2018

Как уже упоминалось в комментариях, вы ищете нечеткий поиск. Это не то, что вы можете легко сделать в базе данных, но есть отдельные поисковые системы, которые вы можете использовать:

  • Apache Solr (платформа на основе Apache Lucene)
  • ElasticSearch
  • Hibernate Search (интеграция Hibernate с Apache Lucene)
  • ...

При использовании такого решения вам придется также индексировать свои объекты в поисковой системе. Spring Data может помочь вам в этом, поскольку есть также библиотека для Solr .

Прежде всего вам нужен новый класс, который представляет, как ваша сущность будет выглядеть в Solr. Помните, что вы хотите «сплющить» все, если бы у вас были вложенные отношения:

@Document
public class UserDocument {
    @Id
    @Indexed("id")
    private String id;
    @Indexed("firstName")
    private String firstName;
    @Indexed("lastName")
    private String lastName;
    @Indexed("userName")
    private String userName;

    // ...
}

После этого вы можете написать репозиторий, как вы привыкли к Spring Data:

public interface UserDocumentRepository extends SolrCrudRepository<UserDocument, String> {
    @Query("userName:?0 OR firstName:?0 OR lastName:?0")
    List<UserDocument> findAll(String searchTerm);
}

После этого вы можете сделать что-то вроде этого:

public User create(User input) {
    // Create user in database
    documentRepository.save(new UserDocument(input.getFirstName(), input.getLastName(), input.getUserName());
}

И вы можете запросить нечеткие поиски, используя также хранилище:

documentRepository.findAll("vickz~3");

Это будет использовать запрос, который я только что написал, и будет искать имена, фамилии или имена пользователей, содержащие vickz. ~3 в конце - специальный синтаксис , указывающий, что имя может содержать 3 символа, отличных от того, который я только что использовал (= расстояние редактирования).

Однако это вернет UserDocument сущности Solr. Если вы хотите получить сущности, вам также нужно их найти, что можно сделать по их имени пользователя:

List<String> usernames = documentRepository
    .findAll("vickz~3")
    .stream()
    .map(UserDocument::getUserName)
    .collect(Collectors.toList());
repository.findByUsername(usernames); // Look in database for users matching those usernames
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...