preface

In SpringBoot, Mybatis, Druid and PageHelper are integrated and implemented with multiple data sources. This article introduces ElastiSearch, the most popular search engine, and uses it in combination with SpringBoot.

ElasticSearch is introduced

ElasticSearch is an open source search engine that can be used to store large data quickly. It is a search engine that can be used to store large data quickly. Search and analysis. ElasticSearch features: Distributed, high availability, asynchronous write, multiple apis, document oriented. ElasticSearch core concepts: Near real-time, clustering, node (save data), index, sharding (index sharding), replica (sharding can set multiple copies). It can quickly store, search and analyze huge amounts of data. ElasticSearch use cases: Wikipedia, Stack Overflow, Github, and more.

Elasticsearch SpringBoot integration

Before using SpringBoot to integrate Elasticsearch, we should look at the relationship between versions.

Spring Boot Version (x) Spring Data Elasticsearch Version (y) Elasticsearch Version (z)
X < = 1.3.5 Y < = 1.3.4 Z < = 1.7.2 *
X > = 1.4 x 2.0.0 < = y < 5.0.0 * * 2.0.0 <= z < 5.0.0**

Here we are using SpringBoot version 1.5.9 and Elasticsearch version 2.3.5.

Elasticsearch is wrapped in SpringBoot, and the DAO layer interface inherits ElasticsearchRepository class, which implements many methods, such as CRUD methods.

The use of SpringData

First of all, make relevant preparations before using it.

Maven configuration is as follows:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> < version > 1.5.9. RELEASE < / version > < / dependency > < the dependency > < groupId > org. Springframework. Boot < / groupId > < artifactId > spring - the boot - starter - data - elasticsearch < / artifactId > < version > 1.5.9. RELEASE < / version > < / dependency >Copy the code

application.propertiesThe configuration of the

spring.data.elasticsearch.repositories.enabled = trueSpring. Data. Elasticsearch. Cluster - nodes = 127.0.0.1 \ : 9300Copy the code

Note: 9300 is the Java client port. 9200 is a Restful HTTP interface.

More configurations:

Spring. Data. Elasticsearch. Cluster -name elasticsearch cluster name. (the default value: elasticsearch) spring. Data. Elasticsearch. Cluster nodes cluster node address list, separated by commas. If not specified, a client node is started. Spring. Data. Elasticsearch. Propertie used to configure additional properties for the client. Spring. Data. Elasticsearch. Repositories. Elasticsearch enabled open warehouse. (Default:true).Copy the code

The code

Entity class

@Document(indexName = "userindex".type = "user") public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; /** id */ private Long id; /** name */ private String name; /** age */ private Integer age; /** description */ private String description; Private String createtm; // getters and setters omitted}Copy the code

When SpringData is used, it needs to set indexName and Type in the entity class, which is equivalent to libraries and tables when compared to traditional databases. Note that both indexName and Type must be lowercase!!

Dao layer

public interface UserDao extends ElasticsearchRepository<User, Long>{
}
Copy the code

The DAO layer is a bit simpler, just inherit the ElasticsearchRepository class. The main methods are Save, DELETE, and search. The save methods are similar to insert and update methods. The delete method mainly deletes data and index libraries. Search is a query, including some common queries, such as paging, weight and so on.

The Service layer

@Service
public class UserServiceImpl implements UserService {
	@Autowired
    private UserDao userDao;
	@Override
	public boolean insert(User user) {
		boolean falg=false;
		try{
			userDao.save(user);
			falg=true;
		}catch(Exception e){
			e.printStackTrace();
		}
		return falg;
	}

	@Override
	public List<User> search(String searchContent) {
		  QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent);
		  System.out.println("Query statement :"+builder);
          Iterable<User> searchResult = userDao.search(builder);
          Iterator<User> iterator = searchResult.iterator();
          List<User> list=new ArrayList<User>();
          while (iterator.hasNext()) {
       	   	list.add(iterator.next());
          }
       returnlist; } @Override public List<User> searchUser(Integer pageNumber, Integer pageSize,String searchContent) {Pageable Pageable = new PageRequest(pageNumber, pageSize); QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent); SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(builder).build(); System.out.println("Query statement :" + searchQuery.getQuery().toString());
        Page<User> searchPageResults = userDao.search(searchQuery);
        returnsearchPageResults.getContent(); } @ Override public List < User > searchUserByWeight (String searchContent) {/ / query FunctionScoreQueryBuilder according to weightfunctionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name", searchContent)),
                    ScoreFunctionBuilders.weightFactorFunction(10))
                .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("description", searchContent)),
                        ScoreFunctionBuilders.weightFactorFunction(100)).setMinScore(2);
        System.out.println("Query statement :" + functionScoreQueryBuilder.toString());
        Iterable<User> searchResult = userDao.search(functionScoreQueryBuilder);
        Iterator<User> iterator = searchResult.iterator();
        List<User> list=new ArrayList<User>();
        while (iterator.hasNext()) {
     	   	list.add(iterator.next());
        }
        returnlist; }}Copy the code

Here I simply write a few methods, the main method is query. Queries include full-text search, paging query and weight query. The higher the score value of the weight is, the higher the query result will be. If the score value of other data is not set, their default score value is 1. If you do not want to query these statements, just use setMinScore to set it to greater than 1.

The test code

Call the interface to add data

New data:

POST http://localhost:8086/api/user

{"id": 1,"name":"Zhang"."age": 20."description":"Joe is a Java developer."."createtm":"The 2018-4-25 11:07:42"}
{"id": 2."name":"Bill"."age": 24,"description":"Li Si is a test engineer."."createtm":"The 1980-2-15 19:01:32"}
{"id": 3."name":"Fifty"."age": 25."description":"Wang Wu is an operations engineer."."createtm":"The 2016-8-21 06:11:32"}
Copy the code

Conduct full-text query requests

http://localhost:8086/api/user?searchContent= engineersCopy the code

return

[{"id": 2."name":"Bill"."age": 14."description":"Li Si is a test engineer."."createtm": "The 1980-2-15 19:01:32"},
{"id": 1,"name":"Zhang"."age": 20."description":"Joe is a Java developer."."createtm": "The 2018-4-25 11:07:42"},
{"id": 3."name":"Fifty"."age": 25."description":"Wang Wu is an operations engineer."."createtm": "The 2016-8-21 06:11:32"}]
Copy the code

Make paging query requests

http://localhost:8086/api/user?pageNumber=0&pageSize=2&searchContent= engineersCopy the code

return

[{"id": 2."name":"Bill"."age": 14."description":"Li Si is a test engineer."}, {"id": 1,"name":"Zhang"."age": 20."description":"Joe is a Java developer."}]
Copy the code

Make weight query request

http://localhost:8086/api/user2?searchContent= li siCopy the code

return

[{"id": 2."name":"Bill"."age": 24,"description":"Li Si is a test engineer."."createtm":"The 1980-2-15 19:01:32"}]
Copy the code

Weight query print statement:

Query statement :{{"function_score" : {
    "functions": [{"filter" : {
        "bool" : {
          "should" : {
            "match" : {
              "name" : {
                "query" : "Bill"."type" : "boolean"}}}}},"weight": 10.0}, {"filter" : {
        "bool" : {
          "should" : {
            "match" : {
              "description" : {
                "query" : "Bill"."type" : "boolean"}}}}},"weight"] : 100.0},"min_score": 2.0}}Copy the code

Note: In the test, irrelevant data will not be displayed because setMinScore has a minimum weight of 2. If you want to display it, remove it from your code.

After adding data, you can enter http://localhost:9200/_plugin/head/ in your browser and click basic Query to view the added data. If you want to use the sentence query, you can print the program console query statement paste to the query interface for query!

Note: I installed ElasticSearch on Windows with the ES plugin head, which is shown at the end of this article.

There are other ways to manipulate ElasticSearch besides SpringData. For example, the native ElasticSearch Api is implemented using the TransportClient class. Or you can use the Spring wrapper to inject beans at the Service layer. Example:

@Autowired
 ElasticsearchTemplate elasticsearchTemplate; 
Copy the code

However, there are limitations in all of the above methods. As ElasticSearch server version changes, the Java API changes, and the client code may need to be rewritten. For ElasticSearch, JestClient is an extension of the HttpRest interface for ElasticSearch. It is available for versions above ElasticSearch2.x. No need to change the code for ElasticSearch server version changes!

JestClient

First add the following dependencies in Maven:

<dependency> <groupId> IO. Searchbox </groupId> <artifactId>jest</artifactId> <version>5.3.3</version> </dependency>Copy the code

Then write the relevant test code. The comments in the code should be complete, so I won’t go over the code here.

import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import com.pancm.pojo.User;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.core.Bulk;
import io.searchbox.core.BulkResult;
import io.searchbox.core.Delete;
import io.searchbox.core.DocumentResult;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.indices.CreateIndex;
import io.searchbox.indices.DeleteIndex;
import io.searchbox.indices.mapping.GetMapping;
import io.searchbox.indices.mapping.PutMapping;

public class JestTest {  
	    private static JestClient jestClient;  
	    private static String indexName = "userindex";  
//	    private static String indexName = "userindex2";  
	    private static String typeName = "user";  
	    private static String elasticIps="http://192.169.2.98:9200";
//	    private static String elasticIps="http://127.0.0.1:9200";
		
	    
	    public static void main(String[] args) throws Exception {
	        jestClient = getJestClient();  
	        insertBatch();
	        serach1();
	        serach2();
	        serach3();
	        jestClient.close();  
	        
		}
	    
	    private static  JestClient getJestClient() {  
	    	JestClientFactory factory = new JestClientFactory();  
			factory.setHttpClientConfig(new HttpClientConfig.Builder(elasticIps).connTimeout(60000).readTimeout(60000).multiThreaded(true).build());  
	        return factory.getObject();  
	    }  
	    
	    public static void insertBatch() {
			List<Object> objs = new ArrayList<Object>();
			objs.add(new User(1L, "Zhang", 20, "Joe is a Java developer."."The 2018-4-25 11:07:42"));
			objs.add(new User(2L, "Bill", 24, "Li Si is a test engineer."."The 1980-2-15 19:01:32"));
			objs.add(new User(3L, "Fifty", 25, "Wang Wu is an operations engineer."."The 2016-8-21 06:11:32"));
			boolean result = false;
			try {
				result = insertBatch(jestClient,indexName, typeName,objs);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("Batch add :"+result); } /** * full text search */ public static voidserach1() {
			String query ="Engineer"; try { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.queryStringQuery(query)); Searchsourcebuilder.from (0).size(2); System.out.println("Full-text search query statement :"+searchSourceBuilder.toString());
				System.out.println("Full text search results returned :"+search(jestClient,indexName, typeName, searchSourceBuilder.toString())); } catch (Exception e) { e.printStackTrace(); }} /** * public static voidserach2() {
			try {
				SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
		    	searchSourceBuilder.query(QueryBuilders.termQuery("age", 24)); 
		    	System.out.println("Exact search query statement :"+searchSourceBuilder.toString());
				System.out.println("Exact search returns result :"+search(jestClient,indexName, typeName, searchSourceBuilder.toString())); } catch (Exception e) { e.printStackTrace(); }} /** * interval search */ public static voidserach3() {
			String createtm="createtm";
			String from="The 2016-8-21 06:11:32";
			String to="The 2018-8-21 06:11:32";
			
			try {
				SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
		    	searchSourceBuilder.query(QueryBuilders.rangeQuery(createtm).gte(from).lte(to)); 
		    	System.out.println("Interval search statement :"+searchSourceBuilder.toString());
				System.out.println("Interval search result returned :"+search(jestClient,indexName, typeName, searchSourceBuilder.toString())); } catch (Exception e) { e.printStackTrace(); } /** * create index * @param indexName * @return
	     * @throws Exception
	     */
	    public boolean createIndex(JestClient jestClient,String indexName) throws Exception {  
	        JestResult jr = jestClient.execute(new CreateIndex.Builder(indexName).build());  
	        returnjr.isSucceeded(); } /** * Add data * @param indexName * @paramtypeName
	     * @param source
	     * @return
	     * @throws Exception
	     */
	    public boolean insert(JestClient jestClient,String indexName, String typeName, String source) throws Exception {  
	        PutMapping putMapping = new PutMapping.Builder(indexName, typeName, source).build();  
	        JestResult jr = jestClient.execute(putMapping);  
	        returnjr.isSucceeded(); } /** * query data * @param indexName * @paramtypeName
	      * @return
	      * @throws Exception
	      */
	    public static String getIndexMapping(JestClient jestClient,String indexName, String typeName) throws Exception {  
	        GetMapping getMapping = new GetMapping.Builder().addIndex(indexName).addType(typeName).build();  
	        JestResult jr =jestClient.execute(getMapping);  
	        returnjr.getJsonString(); } /** * Add data in batches * @param indexName * @paramtypeName
	    * @param objs
	    * @return
	    * @throws Exception
	    */
	    public static boolean insertBatch(JestClient jestClient,String indexName, String typeName, List<Object> objs) throws Exception {  
	        Bulk.Builder bulk = new Bulk.Builder().defaultIndex(indexName).defaultType(typeName);  
	        for (Object obj : objs) {  
	            Index index = new Index.Builder(obj).build();  
	             bulk.addAction(index);  
	        }  
	        BulkResult br = jestClient.execute(bulk.build());  
	        returnbr.isSucceeded(); } /** ** full text search * @param indexName * @paramtypeName
	     * @param query
	     * @return
	     * @throws Exception
	     */
	    public static String search(JestClient jestClient,String indexName, String typeName, String query) throws Exception {  
	    	 Search search = new Search.Builder(query)
	    	 .addIndex(indexName)
	    	 .addType(typeName)  
	    	 .build(); 
	        JestResult jr = jestClient.execute(search);  
//	        System.out.println("--"+jr.getJsonString());
//	        System.out.println("--"+jr.getSourceAsObject(User.class));
	        returnjr.getSourceAsString(); } /** * delete index * @param indexName * @return
	    * @throws Exception
	    */
	    public boolean delete(JestClient jestClient,String indexName) throws Exception {  
	        JestResult jr = jestClient.execute(new DeleteIndex.Builder(indexName).build());  
	        returnjr.isSucceeded(); } /** * delete data * @param indexName * @paramtypeName
	    * @param id
	    * @return
	    * @throws Exception
	    */
	    public boolean delete(JestClient jestClient,String indexName, String typeName, String id) throws Exception {  
	        DocumentResult dr = jestClient.execute(new Delete.Builder(id).index(indexName).type(typeName).build());  
	        return dr.isSucceeded();  
	    }  
Copy the code

Note: ElasticSearch 2.3.5 is installed on the local Windows OS, and 6.2 is installed on the Linux server.

The test results

Full-text search

Full-text search query statement :{"from": 0."size": 2."query" : {
    "query_string" : {
      "query" : "Engineer"}}} full text search result :{"id": 1,"name":"Zhang"."age": 20."description":"Joe is a Java developer."."createtm":"The 2018-4-25 11:07:42"}, {"id": 2."name":"Bill"."age": 24,"description":"Li Si is a test engineer."."createtm":"The 1980-2-15 19:01:32"}
Copy the code

Match the search

Precise search query statement :{"query" : {
    "term" : {
      "age": 24}}} precise search results :{"id": 2."name":"Bill"."age": 24,"description":"Li Si is a test engineer."."createtm":"The 1980-2-15 19:01:32"}
Copy the code

Time interval search

Interval search statement :{"query" : {
    "range" : {
      "createtm" : {
        "from" : "The 2016-8-21 06:11:32"."to" : "The 2018-8-21 06:11:32"."include_lower" : true."include_upper" : true}}}} Interval search result :{"id": 1,"name":"Zhang"."age": 20."description":"Joe is a Java developer."."createtm":"The 2018-4-25 11:07:42"}
Copy the code

After adding data, we can query related information in Kibana of Linux, and the query results are as follows:

Note :Kibana is an open source software in ELK. Kibana’s log analysis friendly Web interface for Logstash and ElasticSearch helps aggregate, analyze, and search important data logs.

The tests in the code above returned the results we expected. Only a few of them are used about JestClient. For more information, see the official documentation of JestClient.

Windows installation ElasticSearch

1, the file to download address: https://www.elastic.co/downloads choose ElasticSearch related version, and then select the suffix called ZIP file to download, download after decompression.

2, start Elasticsearch, go to the bin directory, run elasticSearch. bat, and enter localhost:9200.

Go to the bin directory, open CMD, and enter plugin install mobz/ Elasticsearch -head. http://localhost:9200/_plugin/head/ If the page is displayed, the installation is successful!

4. Enter the bin directory, open CMD, enter the DOS interface, and enter: Bat install service.bat start Enter services. MSC to view the running status of es.

other

API ElasticSearch website address: https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.3/index.html

JestClientGithub address: https://github.com/searchbox-io/Jest

I put the project on Github. https://github.com/xuwujing/springBoot

If you feel good, I hope you can give me a STAR. That’s the end of this article. Thank you for reading.

Copyright Notice: Author: nothing Blog garden reference: http://www.cnblogs.com/xuwujing CSDN reference: http://blog.csdn.net/qazwsxpcm personal blog reference: http://www.panchengming.com original, reproduced please indicate the source, thank you!