Java代码的索引库:
package cn.itcast.hotel;
import lombok.AccessLevel;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
/**
* es连接
*/
@SpringBootTest
public class HotelIndexTest {
private RestHighLevelClient client;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.136.128:9200")
));
}
@Test
public void init()
{
System.out.println(client);
}
/**
* 创建索引库
* @throws IOException
*/
@Test
public void createIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("hotel");
request.source("json", XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);
}
/**
* 删除一个索引库
* @throws IOException
*/
@Test
public void deleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
client.indices().delete(request,RequestOptions.DEFAULT);
}
/**
* 查看一个索引库是否存在
* @throws IOException
*/
@Test
public void exitsIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("hotel");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists?"存在":"不存在");
}
@AfterEach
void tearDown() {
try {
client.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Java代码文档操作:
package cn.itcast.hotel;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.api.R;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
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.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class HotelDocTest {
private RestHighLevelClient client;
@Autowired
private IHotelService hotelService;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.136.128:9200")
));
}
@AfterEach
void tearDown() {
try {
client.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 往索引库中插入一条数据
* @throws IOException
*/
@Test
public void addDocumentIndex() throws IOException {
Hotel hotel = hotelService.getById(46829L);
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest request = new IndexRequest("hotel");
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON).id(hotel.getId().toString());
client.index(request, RequestOptions.DEFAULT);
}
//查询某一条数据,根据id查询
@Test
public void queryIndex() throws IOException {
GetRequest request = new GetRequest("hotel","46829");
GetResponse document = client.get(request, RequestOptions.DEFAULT);
String index = document.getIndex();
Map<String, Object> source = document.getSource();
System.out.println(source);
}
//更改某一个文档数据的内容
@Test
public void updateIndex() throws IOException {
UpdateRequest request = new UpdateRequest("hotel","46829");
request.doc(
"pic","Cc",
"score","115"
);
client.update(request,RequestOptions.DEFAULT);
}
//删除某一个id的文档数据
@Test
public void deleteIndex() throws IOException {
DeleteRequest request = new DeleteRequest("hotel","46829");
client.delete(request,RequestOptions.DEFAULT);
}
//批量操作,bulk,可以批量插入,删除,更新
//批量插入
@Test
public void bulkIndex() throws IOException {
BulkRequest request = new BulkRequest();
List<Hotel> list = hotelService.list();
list.stream().forEach((hotel)->{ //stream流操作,实现循环操作
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest indexRequest = new IndexRequest("hotel");
indexRequest.source(JSON.toJSONString(hotelDoc),XContentType.JSON).id(hotel.getId().toString());
request.add(indexRequest);
});
client.bulk(request,RequestOptions.DEFAULT);
}
}
索引库查询搜索操作:
#全部查询,默认返回页数大小为10个
GET /hotel/_search
{
"query": {
"match_all": {}
}
}
# 组合查询,根据符合的score值,做排序
GET /hotel/_search
{
"query": {
"match": {
"all": "北京酒店"
}
}
}
#在多个字段中查询,跟组合查询差不多,但是这个浪费时间
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["name","brand","business"]
}
}
}
#精准查询,例如keyword或者其他数字。
GET /hotel/_search
{
"query": {
"term": {
"city": {
"value": "上海"
}
}
}
}
#范围查询,根据某个数字的大小范围
GET /hotel/_search
{
"query": {
"range": {
"price": {
"gte": 10, #大于等于
"lte": 200 #小于等于
}
}
}
}
#坐标查询,范围查询,根据当前坐标点,查询某个范围的
GET /hotel/_search
{
"query": {
"geo_distance":
{
"distance": "3km",
"position": "31.21, 121.5"
}
}
}
DELETE /hotel
#functionscore查询,自己根据查出来的文档
#再将这些文档进行一个筛选
#让你想让他评分高的高,排在前面
GET /hotel/_search
{
"query": {
"function_score": {
"query": {
"match": {
"all": "北京酒店"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
},
"weight": 5
}
],
"boost_mode": "multiply"
}
}
}
复合查询:简单查询的组合,实现复杂的查询
相关性算分(function score):算分查询,可以控制文档相关性算分,控制文档排名。例如百度竞价
bool查询:
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"brand": {
"value": "如家"
}
}
}
],
"must_not": [
{
"range": {
"FIELD": {
"gt": 400
}
}
}
],
"filter": [
{
"geo_distance": {
"distance": "10km",
"position": "31.2, 121.5"
}
}
]
}
}
}
数字排序sort:(双条件排序)
#sort排序,如果指定排序方式。默认的打分为null
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"score": {
"order": "desc"
},
"price": {
"order": "asc"
}
}
]
}
地理坐标排序(根据排序会给出sort距离)
#sort排序坐标121.612282,31.034661,按照这个坐标升序排序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"position": {
"lat": 31.034661,
"lon": 121.612282
},
"order": "asc",
"unit": "km"
}
}
]
}
分页查询(类似于MySQL的 limit offset(开始的位置,偏移量),raw(行数)):
#分页查询(默认页大小为10,开始位置为0)
GET /hotel/_search
{
"query": {
"match_all": {}
},
"from": 0, #从哪里开始
"size": 3 #页数大小
}
from+size实现方式:
from+size是通过将0-某个数字的文档全部查询出来,然后通过截取方式获取某段文档。比如查询9990-10000的数据,es会首先查询出0-10000的数据,在对0-10000的数据截取,截取出9990-10000的文档数据。
如果是在分布式集群下面(es集群是为了尽可能多的存储数据,所以每个集群的数据不同)
你查询9990-10000的数据就是从每个集群中查询0-10000的数据,然后将所有文档数据排序,然后将数据截取。
造成的问题,每个集群查需要时间,数据之间的排序需要时间,耗费的时间很大很大。
查询高亮处理:(通过服务端给的标签<em></em>,前段给这个字段这是css)
#搜索的字段必须与高亮的字段匹配,如果不匹配可以设置"require_field_match": "false"
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
"fields": {
"name": {
"require_field_match": "false"
}
}
}
}
Java代码:
package cn.itcast.hotel;
import cn.itcast.hotel.service.IHotelService;
import com.baomidou.mybatisplus.extension.api.R;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
public class HotelSearchTest {
private RestHighLevelClient client;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.136.128:9200")
));
}
@AfterEach
void tearDown() {
try {
client.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//查询全部,显示10个
@Test
public void matchAll() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchAllQuery());
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//根据字段查询,一个字段
@Test
public void match() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchQuery("brand","如家"));
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
print(search);
}
//精确查询
@Test
public void term() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.termQuery("city","北京"));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//范围查询
@Test
public void range() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(150));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//bool查询
@Test
public void bool() throws IOException {
SearchRequest request = new SearchRequest("hotel");
BoolQueryBuilder must = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("city", "上海"));
must.filter(QueryBuilders.termQuery("brand","如家"));
request.source().query(must);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//排序设置
@Test
public void sort() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.termQuery("city","北京"));
request.source().sort("price", SortOrder.ASC);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//分页和页数大小
@Test
public void page() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.termQuery("city","北京"));
request.source().size(3).from(2);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
//高亮设置
@Test
public void highlight() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().query(QueryBuilders.matchQuery("city","北京"));
request.source().highlighter(new HighlightBuilder().field("city").requireFieldMatch(false));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
print(response);
}
private void print(SearchResponse response)
{
SearchHits searchHits = response.getHits();
SearchHit[] hits = searchHits.getHits();
long value = searchHits.getTotalHits().value;
System.out.println("总数:"+value);
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
}
}
}