使用Elasticsearch 真是遇到太多坑了。网上的一搜索抄袭太多,问题一个都解决不了。
后台通过实践,自己总算调通了。现在和后台的同志献上代码,希望大家别再走弯路。
第一步:
下载安装,部署elasticsearch 集群,不难,大家可以在网上搜索,给你们推荐慕课网,的“瓦力”,里面讲了如何部署和对接。
首先创建 索引:
新建索引
poistion 字段, type 是 geo_point
name 字段 type 是 text
put geo
put geo/geo/_mapping
{
"properties": {
"location": {
"type": "geo_point"
}
}
}
put geo/geo/1
{
"location": {
"lat": 0.1,
"lon": 0.1
}
}
put geo/geo/2
{
"location": {
"lat": 50.1,
"lon": 7.1
}
}
put geo/geo/3
{
"location": {
"lat": 5.1,
"lon": 3.1
}
}
get geo/geo/_search
{
"query": {
"match_all": {
}
},
"sort": [
{
"_geo_distance": {
"location": {"lat":0, "lon":0},
"order":"asc",
"unit":"km"
}
}
]
}
建立好后,就可以直接插入数据了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
//get set 自己写, 我使用的是 lombok
public class EsShop implements Serializable {
private Long id;
private String title;
private String name;
private GeoPoint position;
private String tag;
private double distance;
数据操作
@Component
public class SearchService {
@Autowired
private JestClient jestClient;
private static final String INDEX_NAME = "jack";
/**
* 表名
*/
private static final String TABLE_NAME = "shop";
/**
* 搜索关键词的字段
*/
private static final String FIELD_NAMES = "title,tag";
public boolean addShop(EsShop shop) {
Index.Builder builder = new Index.Builder(shop);
Index index = builder.index(INDEX_NAME).type(TABLE_NAME).build();
return executeBoolean(index);
}
public List<EsShop> getShop(String searchKey, Double lon, Double lat, int pageNumber, int pageSize) {
Long nowTime = System.currentTimeMillis();
SearchSourceBuilder builder = new SearchSourceBuilder();
int start = (pageNumber - 1) * pageSize;
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchKey, FIELD_NAMES.split(","));
builder.query(multiMatchQueryBuilder)
.from(start)
.size(pageSize);
//获取距离多少公里 这个才是获取点与点之间的距离的
GeoDistanceSortBuilder sortBuilder = new GeoDistanceSortBuilder("position", lat, lon);
sortBuilder.unit(DistanceUnit.METERS);
sortBuilder.order(SortOrder.ASC);
sortBuilder.geoDistance(GeoDistance.ARC);
// GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("position", lat, lon)
// .unit(DistanceUnit.METERS)
// .order(SortOrder.ASC);
builder.sort(sortBuilder);
System.out.println(System.currentTimeMillis() - nowTime);
Search search = new Search.Builder(builder.toString())
.addIndex(INDEX_NAME)
.addType(TABLE_NAME).build();
try {
JestResult ret = jestClient.execute(search);
JsonObject jsonObject = ret.getJsonObject();
EsJson esJson = JSON.parseObject(ret.getJsonString(), EsJson.class);
// EsJson esJson = ret.getSourceAsObject(EsJson.class);
List<EsJson.HitsBeanX.HitsBean> hits = esJson.getHits().getHits();
List<EsShop> shopList = new ArrayList<>();
for (int i = 0; i < hits.size(); i++) {
EsShop shop = hits.get(i).get_source();
shop.setDistance(hits.get(i).getSort().get(0));
shopList.add(shop);
}
return shopList;
} catch (IOException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
public List<EsShop> getShop(String searchKey, int pageNumber, int pageSize) {
SearchSourceBuilder builder = new SearchSourceBuilder();
int start = (pageNumber - 1) * pageSize;
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchKey, FIELD_NAMES.split(","));
builder.query(multiMatchQueryBuilder)
.from(start)
.size(pageSize);
return execute(builder.toString());
}
public boolean deleteShop(Long shopId) {
Delete delete = new Delete.Builder(shopId + "").index(INDEX_NAME).type(TABLE_NAME).refresh(true).build();
return executeBoolean(delete);
}
private boolean executeBoolean(Action index) {
try {
JestResult result = jestClient.execute(index);
return null != result && result.isSucceeded();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
private List<EsShop> execute(String sql) {
Search search = new Search.Builder(sql)
.addIndex(INDEX_NAME)
.addType(TABLE_NAME).build();
try {
JestResult ret = jestClient.execute(search);
List<EsShop> shopList = ret.getSourceAsObjectList(EsShop.class);
return shopList;
} catch (IOException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
}
测试:
@Autowired
SearchService shopRepository;
@Test
public void test2() throws IOException {
double lon = 100.123;
double lat = 10.123;
List<EsShop> b = shopRepository.getShop("西瓜", lon, lat, 1, 10);
for (EsShop s : b) {
System.out.println(s.toString());
}
}
@Test
public void test() throws IOException {
String[] sre = {"火锅", "串串", "回锅肉", "水煮肉", "西葫芦", "西瓜"};
Random random = new Random();
double lon = 100.000;
double lat = 10.000;
for (long i = 0; i < 10000; i++) {
lon += 0.001;
lat += 0.001;
EsShop esShop = new EsShop();
esShop.setId(i);
esShop.setTitle(sre[random.nextInt(5)]);
esShop.setPosition(new GeoPoint(lat, lon));
esShop.setTag(sre[random.nextInt(5)] + "," + sre[random.nextInt(5)]);
boolean b = shopRepository.addShop(esShop);
System.out.println(b + " " + esShop.toString());
}
}