For a complete code sample, please refer to the personal GitHub repository (github.com/KimZing) containing Controller/Repository and test code.

Welcome star, if there is an error, welcome to correct _

I. Introduction to the environment

  • The idea of 2016.3
  • JDK 1.8
  • ElasticSearch 2.4(SpringBoot Starter does not support the latest version of ElasticSearch)

Ii. Introduction to ES

Those of you who have developed Java search know lucene, but Lucene is just a search engine, like a car engine, important but not directly usable. Later, solr search, as we all know, provided the corresponding Web operation interface and Java API operation, but solr’s data concurrency and performance under large data volume are still a certain gap, and ES is born to support distributed cluster.

What is ES? We can compare ES to a Mysql database, which is also used to store data, but provides more search functions than Mysql, such as word segmentation search, correlation search, etc. Besides, the search speed is not at the same level. ES can realize the query speed of millions of data per second. Next, compare the concepts used in ES to Mysql

field explain
index An index is equivalent to a library in Mysql. For example, there is a library called “JD” in which many tables can be created to store different types of data. Tables in ES are types.
type Type, equivalent to a table in Mysql that stores data of the JSON type
document Document, a document is equivalent to a row of Mysql data
shards Sharding, commonly known as partitioning data into several areas for storage, can be understood as mysql library and table (not appropriate).
replicas Backup is the number of backup fragments, which is equivalent to the mysql backup library

ES uses JSON data for data transfer, such as {username:king,age:12}, then the entire JSON data is a document, and username,age is a field.

SpringBoot integrates ES dependencies

// The ES core relies on Starter
compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')
// JNA dependency. Otherwise, classNotFound: Native method Disable is reported when the project is started
compile("Com. Sun. Jna: jna: 3.0.9")
// Add Web support for easy testing
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
Copy the code

4. Configuration files

SpringBoot will automatically generate an ES repository for you, and the project will automatically generate a data folder to store the ES data. If we do not configure the ES instance, SpringBoot will automatically generate the ES instance. Of course, performance will not be good, so we will use our own ES instance.

The dependency structure of data-elasticSearch

spring:
  data:
    #ElasticSearch link address
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: localhost:9300
Copy the code

For details about installing ES, please refer to another of my blog posts, CentOS6.5 installing ES tutorial

Write a storage entity class

There are three main annotations to write an entity class

@document (equivalent to @entity / @table for Hibernate entities) (required)

type The property name The default value instructions
String indexName There is no The name of the index library. You are advised to use the name of the project
String type “” Type, you are advised to name it with the entity name
short shards 5 Default number of partitions
short replica 1 Default number of backups per partition
String refreshInterval “1s” The refresh interval
String indexStoreType “fs” Index file storage type

2. Primary key annotation: @id (equivalent to Hibernate entity primary key @ID annotation) (required)

Just an identifier, no attributes.

3. Attribute annotation @field (equivalent to the @column annotation of Hibernate entities)

@field is optional by default, all attributes are added to ES by default.

type The property name The default value instructions
FileType type FieldType.Auto Automatically detects the type of the property
FileType index FieldIndex.analyzed By default, participles are used
boolean store false The original text is not stored by default
String searchAnalyzer “” Specifies the tokenizer to use for field searches
String indexAnalyzer “” Specifies the tokenizer specified when the field is indexed
String[] ignoreFields {} If a field needs to be ignored

4. Examples of entity classes

@Data  // Lombok annotations, which automatically generate setters/getters, need to import Lombok packages to use.
@Document(indexName = "shop", type = "user", refreshInterval = "0s")
public class User {

    @Id
    private Long id;

    private String username;

    private String realname;

    private String password;

    private Integer age;

    // These three annotations are used for the foreground serialization of Java8 LocalDateTime, which requires the introduction of jSR310 packages
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
    private LocalDateTime birth;

}
Copy the code

6. Compile the warehouse

1. Code writing

<T, ID> <T, ID> <T, ID> <T, ID>

/ * * *@author [email protected]
 * @date2017/11/27 10:10 PM *@descUser repository. */
public interface UserRepository extends ElasticsearchRepository<User.Long>{}Copy the code

ElasticsearchRepository (JPA) ΒΆ Reposiroty (JPA) ΒΆ Spring automatically implements methods based on their names by generating corresponding proxy classes.

2. Basic CRUD operations

ElasticsearchRepository has some basic methods that are already implemented. The names of these methods are well explained so that you can easily understand them

3. Slightly complex operations

Jpa’s built-in methods certainly don’t meet our business needs, so how do we customize our methods? We just define the method name with a specific word, and Spring will parse the method name and generate the corresponding instance for data processing. Isn’t that easy? So let’s use an example from the official Spring documentation.

Let’s take a look at the description of keywords


The keyword Use the sample Equivalent to ES query
And findByNameAndPrice {” bool “: {” must” : [{” field “: {” name” : “? “}}, {” field “: {” price” : “? “}}]}}
Or findByNameOrPrice {” bool “: {” should” : [{” field “: {” name” : “? “}}, {” field “: {” price” : “? “}}]}}
Is findByName {” field “: {” field” : {” name “:”?” }}}}
Not findByNameNot {” bool “: {” must_NOT” : {” field “: {” name” : “?” }}}}
Between findByPriceBetween {” bool “: {” must” : {” range “: {” price” : {” from “:? , “to” πŸ˜• , include_lower: true, include_upper: true}}}}}
LessThanEqual findByPriceLessThan {” bool “: {” must” : {” range “: {” price” : {” from “, null, “to” πŸ˜• , include_lower: true, include_upper: true}}}}}
GreaterThanEqual findByPriceGreaterThan {” bool “: {” must” : {” range “: {” price” : {” from “:? , “to” : null, “include_lower” : true, “include_upper” : true}}}}}
Before findByPriceBefore {” bool “: {” must” : {” range “: {” price” : {” from “, null, “to” πŸ˜• , include_lower: true, include_upper: true}}}}}
After findByPriceAfter {” bool “: {” must” : {” range “: {” price” : {” from “:? , “to” : null, “include_lower” : true, “include_upper” : true}}}}}
Like findByNameLike {” bool “: {” must” : {” field “: {” name” : {” query “:”? * “, “analyze_wildcard” : true}}}}}
StartingWith findByNameStartingWith {” bool “: {” must” : {” field “: {” name” : {” query “:”? * “, “analyze_wildcard” : true}}}}}
EndingWith findByNameEndingWith {” bool “: {” must” : {” field “: {” name” : {” query “:” *?” , “analyze_wildcard” : true}}}}}
Contains/Containing findByNameContaining {” bool “: {” must” : {” field “: {” name” : {” query “:”?” , “analyze_wildcard” : true}}}}}
In findByNameIn(Collectionnames) {” bool “: {” must” : {” bool “: {” should” : [{” field “: {” name” : “? “}}, {” field “: {” name” : “? “}}]}}}}
NotIn findByNameNotIn(Collectionnames) {” bool “: {” must_not” : {” bool “: {” should” : {” field “: {” name” : “?” }}}}}}
True findByAvailableTrue {” bool “: {” must” : {” field “: {” available” : true}}}}
False findByAvailableFalse {” bool “: {” must” : {” field “: {” available” : false}}}}
OrderBy findByAvailableTrueOrderByNameDesc {” sort “: [{” name” : {” order “:” desc “}}], “bool” : {” must “: {” field” : {” available “: true}}}}

Here are a few examples to demonstrate, only the storage layer is listed, the overall operation is tested, no problem, if you need the overall code please go to the Github repository at the top of this article.

/ * * *@author [email protected]
 * @date2017/11/27 10:10 PM *@descUser repository. */
public interface UserRepository extends ElasticsearchRepository<User.Long>{

    /** * Query user * whose name is username@param username
     * @return* /
    List<User> findByUsername(String username);

    /** * query user * whose realname is realname@param username
     * @param realname
     */
    List<User> findByUsernameAndRealname(String username, String realname);

    /** * Query username or realname */
    List<User> findByUsernameOrRealname(String username, String realname);

    /** * query all users whose username is not username *@param username
     * @return* /
    List<User> findByUsernameNot(String username);


    /** * query user ageFrom ageFrom to ageTo *@param ageFrom
     * @param ageTo
     * @return* /
    List<User> findByAgeBetween(Integer ageFrom, Integer ageTo);

    /** * Query the birthdate of the user whose birthdate is less than */
    List<User> findByBirthLessThan(LocalDateTime birthTo);


    /** * Query the birthday segment greater than the birthFrom user *@param birthFrom
     * @return* /
    List<User> findByBirthGreaterThan(LocalDateTime birthFrom);

    /** * Query users whose age is younger than or equal to ageTo */
    List<User> findByAgeBefore(Integer ageTo);

    /** * Query users whose age is greater than or equal to ageFrom *@param ageFrom
     * @return* /
    List<User> findByAgeAfter(Integer ageFrom);

    /** * User name fuzzy query *@param username
     * @return* /
    List<User> findByUsernameLike(String username);


    /** * Query users * that start with start@param start
     * @return* /
    List<User> findByUsernameStartingWith(String start);

    /** * Query user * ending with end@return* /
    List<User> findByUsernameEndingWith(String end);

    /** * Query user name containing word *@param word
     * @return* /
    List<User> findByUsernameContaining(String word);

    /** * Query user * whose name belongs to usernames@param usernames
     * @return* /
    List<User> findByUsernameIn(Collection<String> usernames);

    /** * Query user * whose name does not belong to usernames@param usernames
     * @return* /
    List<User> findByUsernameNotIn(Collection<String> usernames);

    Select * from user where id > idTo, age > ageTo, name > start, age > idTo, age > idTo, age > idTo, age > idTo, age > idTo, age > idTo, age > idTo, age > idTo@return* /
    List<User> findByAgeBeforeAndUsernameStartingWithAndIdGreaterThanOrderByAgeDesc(Integer ageTo, String start, Long idTo);

}
Copy the code

4. More complex operations

We can use the @query annotation to Query, which requires us to write our own ES Query, which requires us to know ES Query, which is easy to do. Look at the official example

public interface BookRepository extends ElasticsearchRepository<Book.String> {
        @Query("{\"bool\" : {\"must\" : {\"field\" : {\"name\" : \"? 0 \ "}}}}")
        Page<Book> findByName(String name,Pageable pageable);
}
Copy the code

5. You can also query in a manner similar to The Criteria in Hibernate.

In this case, we need to write our own query criteria, inject UserRepository into the class, pass in the query parameters using the search method, and obtain the query results as shown in the following example:

/ * * *@author [email protected]
 * @date2017/11/28 12:53 PM *@descUser services. */
@Service
public class UserService {

    @Resource
    UserRepository userRepository;

    public Page<User> getUsers(a) {
        / / create a builder
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        // The builder has must, should, and mustNot equivalent to and, or, and not
        // Set fuzzy search for users whose real names contain gold
        builder.must(QueryBuilders.fuzzyQuery("realname"."Gold"));
        // Set the user name to king
        builder.must(new QueryStringQueryBuilder("king").field("username"));

        / / sorting
        FieldSortBuilder sort = SortBuilders.fieldSort("age").order(SortOrder.DESC);

        // Set paging
        / / = = = = attention! Es's pagination API, like Hibernate's, starts at ========= from page 0
        PageRequest page = new PageRequest(0.2);

        // Build the query
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // Set the search criteria to the build
        nativeSearchQueryBuilder.withQuery(builder);
        // Set paging to the build
        nativeSearchQueryBuilder.withPageable(page);
        // Set the sort to the build
        nativeSearchQueryBuilder.withSort(sort);
        / / NativeSearchQuery production
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

        // Execute to return a page of wrapped results
        Page<User> resutlList = userRepository.search(query);

        returnresutlList; }}Copy the code

Source: author: KimZing CSDN, blog.csdn.net/KingBoyWorl…