ElasticSearch的java api

/ 工具和中间件 / 2 条评论 / 1663浏览

elasticsearch的java api

索引操作

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

import java.io.IOException;

public class TestElasticSearch4J {
	/**
	 * 连接elasticsearch库
	 */
	private static RestHighLevelClient client = new RestHighLevelClient(
	        RestClient.builder(
	                new HttpHost("localhost", 9200, "http")
	        ));
	
	public static void main(String[] args) throws IOException {
		String indexName = "imwj";
		
		if(!checkExistIndex(indexName)){
			createIndex(indexName);			
		}
		if(checkExistIndex(indexName)){
			deleteIndex(indexName);
		}
		checkExistIndex(indexName);
		client.close();
	}

	/**
	 * 校验索引是否存在
	 * @param indexName
	 * @return
	 * @throws IOException
	 */
	private static boolean checkExistIndex(String indexName) throws IOException {
		boolean result =true;
		try {
	        OpenIndexRequest openIndexRequest = new OpenIndexRequest(indexName);
	        client.indices().open(openIndexRequest).isAcknowledged();

	    } catch (ElasticsearchStatusException ex) {
	        //只能通过异常来判断索引是否存在
	        String m = "Elasticsearch exception [type=index_not_found_exception, reason=no such index]";
	        if (m.equals(ex.getMessage())) {
	        	result = false;
	        }
	    }
		if(result)
			System.out.println("索引:" +indexName + " 是存在的");
		else
			System.out.println("索引:" +indexName + " 不存在");
		
		return result;
		
	}

	/**
	 * 删除索引
	 * @param indexName
	 * @throws IOException
	 */
	private static void deleteIndex(String indexName) throws IOException {
		DeleteIndexRequest request = new DeleteIndexRequest(indexName);
		client.indices().delete(request);
		System.out.println("删除了索引:"+indexName);

		
	}

	/**
	 * 创建索引
	 * @param indexName
	 * @throws IOException
	 */
	private static void createIndex(String indexName) throws IOException {
		CreateIndexRequest request = new CreateIndexRequest(indexName);
		client.indices().create(request);
		System.out.println("创建了索引:"+indexName);
	}
     
}

文档操作

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

import java.io.IOException;
import java.util.HashMap;

public class TestElasticSearch4J {
	private static RestHighLevelClient client = new RestHighLevelClient(
			RestClient.builder(
					new HttpHost("localhost", 9200, "http")
			));

	private static String indexName = "imwj";

	public static void main(String[] args)throws IOException {
//确保索引存在
		if(!checkExistIndex(indexName)){
			createIndex(indexName);
		}
		//准备数据
		Product product = new Product();
		product.setId(1);
		product.setName("product 1");

		//增加文档
		addDocument(product);
		//获取文档
		getDocument(1);
		//修改数据
		product.setName("product 2");
		//修改文档
		updateDocument(product);
		//获取文档
		getDocument(1);
		//删除文档
		deleteDocument(1);
		//获取文档
		getDocument(1);

		client.close();
	}

	/**
	 * 添加文档
	 * @param product
	 * @throws IOException
	 */
	public static void addDocument(Product product)throws IOException{
		HashMap<String, Object> jsonMap = new HashMap<>();
		jsonMap.put("name", product.getName());
		IndexRequest indexRequest = new IndexRequest(indexName, "product", String.valueOf(product.getId())).source(jsonMap);
		client.index(indexRequest);
		System.out.println("已经向ElasticSearch服务器增加产品:"+product);
	}

	/**
	 * 删除文档
	 * @param id
	 * @throws IOException
	 */
	private static void deleteDocument(int id)throws IOException{
		DeleteRequest deleteRequest = new DeleteRequest(indexName, "product", String.valueOf(id));
		client.delete(deleteRequest);
		System.out.println("已经从ElasticSearch服务器上删除id="+id+"的文档");
	}

	/**
	 * 更新文档
	 * @param product
	 * @throws IOException
	 */
	private static void updateDocument(Product product)throws IOException{
		UpdateRequest updateRequest = new UpdateRequest(indexName, "product", String.valueOf(product.getId()))
				.doc("name", product.getName());
		client.update(updateRequest);
		System.out.println("已经在ElasticSearch服务器上修改:"+product);
	}

	/**
	 * 获取文档
	 * @param id
	 * @throws IOException
	 */
	private static void getDocument(int id)throws IOException{
		GetRequest getRequest = new GetRequest(indexName, "product", String.valueOf(id));
		GetResponse response = client.get(getRequest);
		if(!response.isExists()){
			System.out.println("检查到服务器上 "+"id="+id+ "的文档不存在");
		}else {
			String source = response.getSourceAsString();
			System.out.print("获取到服务器上 "+"id="+id+ "的文档内容是:");
			System.out.println(source);
		}
	}

	/**
	 * 校验索引是否存在
	 * @param indexName
	 * @return
	 * @throws IOException
	 */
	private static boolean checkExistIndex(String indexName)throws IOException{
		boolean result = true;
		try {
			OpenIndexRequest openIndexRequest = new OpenIndexRequest(indexName);
			client.indices().open(openIndexRequest).isShardsAcknowledged();
		}catch (ElasticsearchStatusException ex){
			//只能通过异常来判断索引是否存在
			String m = "Elasticsearch exception [type=index_not_found_exception, reason=no such index]";
			if (m.equals(ex.getMessage())) {
				result = false;
			}
		}
		return result;
	}

	/**
	 * 创建索引
	 * @param indexName
	 * @throws IOException
	 */
	private static void createIndex(String indexName)throws IOException{
		CreateIndexRequest request = new CreateIndexRequest(indexName);
		client.indices().create(request);
		System.out.println("创建了索引:"+indexName);
	}

	/**
	 * 删除索引
	 * @param indexName
	 * @throws IOException
	 */
	private static void deleteIndex(String indexName)throws IOException{
		DeleteIndexRequest request = new DeleteIndexRequest(indexName);
		client.indices().delete(request);
		System.out.println("删除了索引:"+indexName);
	}
}

批量插入数据

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

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

public class TestElasticSearch4J {
	private static RestHighLevelClient client = new RestHighLevelClient(
	        RestClient.builder(
	                new HttpHost("localhost", 9200, "http")
	        ));
	private static String indexName = "imwj";
	
	public static void main(String[] args) throws IOException {
		//确保索引存在
		if(!checkExistIndex(indexName)){
			createIndex(indexName);			
		}
		//14万准备数据
		List<Product> products = ProductUtil.file2list("140k_products.txt");
		System.out.println("准备数据,总计"+products.size()+"条");
		batchInsert(products);
		client.close();
	}

	/**
	 * 批量插入一个list集合
	 * @param products
	 * @throws IOException
	 */
	private static void batchInsert(List<Product> products) throws IOException {
		BulkRequest request = new BulkRequest();
		
		for (Product product : products) {
			Map<String,Object> m  = product.toMap();
			IndexRequest indexRequest= new IndexRequest(indexName, "product", String.valueOf(product.getId())).source(m);
			request.add(indexRequest);
		}
		
		client.bulk(request);
		System.out.println("批量插入完成");
	}
}

文档查询操作

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;

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

public class TestElasticSearch4J {
	private static RestHighLevelClient client = new RestHighLevelClient(
	        RestClient.builder(
	                new HttpHost("localhost", 9200, "http")
	        ));
	private static String indexName = "imwj";
	
	public static void main(String[] args) throws IOException {
		String keyword = "时尚连衣裙";
		int start = 0;
		int count = 10;
		
		SearchHits hits = search(keyword, start, count);
		SearchHit[] searchHits = hits.getHits();
		for (SearchHit hit : searchHits) {
			System.out.println(hit.getSourceAsString());
		}
		client.close();
	}

	/**
	 * 查询操作:根据关键字分页查询
	 * @param keyword
	 * @param start
	 * @param count
	 * @return
	 * @throws IOException
	 */
	private static SearchHits search(String keyword, int start, int count) throws IOException {
		SearchRequest searchRequest = new SearchRequest(indexName); 
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 
		//关键字匹配
		MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("name",keyword ); 
		//模糊匹配
		matchQueryBuilder.fuzziness(Fuzziness.AUTO);
		sourceBuilder.query(matchQueryBuilder); 
		//第几页
		sourceBuilder.from(start); 
		//第几条
		sourceBuilder.size(count); 
		searchRequest.source(sourceBuilder);
		//匹配度从高到低
		sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
		SearchResponse searchResponse = client.search(searchRequest);
		SearchHits hits = searchResponse.getHits();
		return hits;
	}
}

springboot中操作

pom文件引入依赖

springboot 1.59

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

yml配置

spring:
  mvc:
    view:
      prefix: /WEB-INF/jsp/
      suffix: .jsp
  data:
    cluster-name: docker-cluster
    cluster-nodes: localhost:9300

server:
  port: 8080

新建实体类

import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;

/**
 * @author langao_q
 * @create 2020-03-17 11:35
 */
@Data
@Document(indexName = "imwj", type = "category")
public class Category {

    private int id;
    private String name;

}

新建dao操作类

直接继承ElasticsearchRepository<Category, Integer>即可

import io.imwj.elasticsearch.pojo.Category;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @author langao_q
 * @create 2020-03-17 11:37
 */
public interface CategoryDAO extends ElasticsearchRepository<Category, Integer> {
}

controller控制类

import io.imwj.elasticsearch.dao.CategoryDAO;
import io.imwj.elasticsearch.pojo.Category;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author langao_q
 * @create 2020-03-17 11:38
 */
@Controller
public class CategoryController {

    @Autowired
    CategoryDAO categoryDAO;

    @ResponseBody
    @GetMapping("/list")
    public Page<Category> list(@RequestParam(value = "start", defaultValue = "0")int start, @RequestParam(value =
            "size", defaultValue = "5")int size, @RequestParam(value = "name", required = false)String name){
        SearchQuery searchQuery=getEntitySearchQuery(start,size,name);
        Page<Category> page = categoryDAO.search(searchQuery);
        return page;
    }

    @GetMapping("/listCategory")
    public String listCategory(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value = "size", defaultValue = "5") int size){
        String query = "商品"; //查询条件,但是并未使用,放在这里,为的是将来使用,方便参考,知道如何用
        SearchQuery searchQuery=getEntitySearchQuery(start,size,query);
        Page<Category> page = categoryDAO.search(searchQuery);
        m.addAttribute("page", page);
        return "listCategory";
    }

    private SearchQuery getEntitySearchQuery(int start, int size, String name) {
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchAllQuery(), //查询所有
                        ScoreFunctionBuilders.weightFactorFunction(100))
               //查询条件
                .add(QueryBuilders.matchPhraseQuery("name", name),
                      ScoreFunctionBuilders.weightFactorFunction(100))
                //设置权重分 求和模式
                .scoreMode("sum")
                //设置权重分最低分
                .setMinScore(10);

        // 设置分页
        Sort sort  = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(start, size,sort);
        return new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder).build();
    }

    @RequestMapping("/addCategory")
    public String addCategory(Category c)throws Exception{
        int id = currenTime();
        c.setId(id);
        categoryDAO.save(c);
        return "redirect:listCategory";
    }

    private int currenTime(){
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
        String format = sdf.format(new Date());
        return Integer.parseInt(format);
    }

    @RequestMapping("/deleteCategory")
    public String deleteCategory(Category c){
        categoryDAO.delete(c);
        return "redirect:listCategory";
    }

    @RequestMapping("/updateCategory")
    public String updateCategory(Category c){
        categoryDAO.save(c);
        return "redirect:listCategory";
    }

    @RequestMapping("/editCategory")
    public String editCategory(int id, Model m){
        Category category = categoryDAO.findOne(id);
        m.addAttribute("c", category);
        return "editCategory";
    }
}

一个例子

书写pojo类

@Data
@Entity
@Table(name="product")
@JsonIgnoreProperties({ "handler","hibernateLazyInitializer" })
@Document(indexName = "tmall_springboot",type = "product") //ElasticSearch增加注解
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @ManyToOne
    @JoinColumn(name="cid")
    private Category category;

    //如果既没有指明 关联到哪个Column,又没有明确要用@Transient忽略,那么就会自动关联到表对应的同名字段,默认@Column(name = "属性名")
    private String name;
    private String subTitle;
    private float originalPrice;
    private float promotePrice;
    private int stock;
    private Date createDate;

    //商品第一张图片
    @Transient
    private ProductImage firstProductImage;
}

增加dao类

public interface ProductESDAO extends ElasticsearchRepository<Product, Integer> {

}

修改service中的操作

在修改mysql数据库时 同步操作es数据库

    /**
     * 增加商品数据
     * @param product
     * @return
     */
    @CacheEvict(allEntries=true)
    public Product add(Product product){
        productESDAO.save(product);
        return productDAO.save(product);
    }

    /**
     * 根据id删除商品数据
     * @param id
     */
    @CacheEvict(allEntries=true)
    public void delete(Integer id){
        productESDAO.delete(id);
        productDAO.delete(id);
    }

    /**
     * 更新商品数据
     * @param product
     * @return
     */
    @CacheEvict(allEntries=true)
    public Product update(Product product){
        productESDAO.save(product);
        return productDAO.save(product);
    }

全文查询

    /**
     * 首页搜索
     * @param keyword
     * @param i
     * @param i1
     * @return
     */
    public List<Product> searh(String keyword, int star, int size) {
        initDatabase2ES();
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchAllQuery(), //查询所有
                        ScoreFunctionBuilders.weightFactorFunction(100))
                //查询条件
                .add(QueryBuilders.matchPhraseQuery("name", keyword),
                        ScoreFunctionBuilders.weightFactorFunction(100))
                //设置权重分 求和模式
                .scoreMode("sum")
                //设置权重分最低分
                .setMinScore(10);
        Sort sort  = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(star, size);
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder).build();
        Page<Product> page = productESDAO.search(build);

        return page.getContent();
    }

    /**
     * 把数据初始化到elasticsearch中
     */
    private void initDatabase2ES(){
        Pageable pageable = new PageRequest(0, 5);
        Page<Product> page = productESDAO.findAll(pageable);
        if(page.getContent().isEmpty()){
            List<Product> products = productDAO.findAll();
            for(Product p : products)
                productESDAO.save(p);
        }
    }