参考资料:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/index.html
注:es版本为2.4.0
1.下载安装:
下载地址:https://www.elastic.co/downloads/elasticsearch
下载之后解压,运行 bin/elasticsearch 即可
2.maven依赖:
2.4
.
0
1.2
.
8
|
3.具体的demo:
package
com.tch.test.elasticsearch.test;
import
java.net.InetAddress;
import
java.net.UnknownHostException;
import
java.util.ArrayList;
import
java.util.Arrays;
import
java.util.Date;
import
java.util.List;
import
java.util.concurrent.ExecutionException;
import
java.util.concurrent.TimeUnit;
import
org.apache.commons.collections4.CollectionUtils;
import
org.apache.commons.lang3.StringUtils;
import
org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import
org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import
org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import
org.elasticsearch.action.delete.DeleteResponse;
import
org.elasticsearch.action.get.GetResponse;
import
org.elasticsearch.action.get.MultiGetItemResponse;
import
org.elasticsearch.action.get.MultiGetResponse;
import
org.elasticsearch.action.index.IndexResponse;
import
org.elasticsearch.action.search.SearchResponse;
import
org.elasticsearch.action.update.UpdateRequest;
import
org.elasticsearch.action.update.UpdateResponse;
import
org.elasticsearch.client.transport.TransportClient;
import
org.elasticsearch.common.transport.InetSocketTransportAddress;
import
org.elasticsearch.common.xcontent.XContentBuilder;
import
org.elasticsearch.common.xcontent.XContentFactory;
import
org.elasticsearch.index.query.BoolQueryBuilder;
import
org.elasticsearch.index.query.QueryBuilders;
import
org.elasticsearch.search.SearchHit;
import
org.elasticsearch.search.sort.SortOrder;
import
com.alibaba.fastjson.JSON;
public
class
ElasticSearchTest {
public
static
final
String INDEX =
"test"
;
public
static
final
String TYPE =
"organization"
;
public
static
TransportClient buildClient()
throws
UnknownHostException {
return
TransportClient.builder().build()
.addTransportAddress(
new
InetSocketTransportAddress(InetAddress.getByName(
"localhost"
),
9300
));
}
public
static
void
closeClient(TransportClient client) {
if
(client !=
null
) {
client.close();
}
}
/**
* 创建mapping(类似数据库的表结构)
*
* @param client
* es client
* @param index
* 索引名字
* @param type
* 索引下type的名字
* @throws Exception
*/
public
static
void
createOrgMapping(TransportClient client)
throws
Exception {
IndicesExistsResponse res = client.admin().indices().prepareExists(INDEX).execute().actionGet();
if
(res.isExists()) {
DeleteIndexRequestBuilder delIdx = client.admin().indices().prepareDelete(INDEX);
delIdx.execute().actionGet();
}
CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(INDEX);
final
XContentBuilder organizationBuilder = XContentFactory.jsonBuilder()
.startObject()
.startObject(TYPE)
.startObject(
"properties"
)
.startObject(
"id"
)
.field(
"type"
,
"long"
)
.endObject()
.startObject(
"name"
)
.field(
"type"
,
"string"
)
.endObject()
.startObject(
"type"
)
.field(
"type"
,
"integer"
)
.endObject()
.startObject(
"industrialModeCodes"
)
.field(
"type"
,
"integer"
)
.endObject()
.startObject(
"updatedAt"
)
.field(
"type"
,
"date"
)
.endObject()
.endObject()
.endObject()
.endObject();
createIndexRequestBuilder.addMapping(TYPE, organizationBuilder);
// MAPPING DONE
createIndexRequestBuilder.execute().actionGet();
}
/**
* 往索引中添加数据
*
* @param client
*/
public
static
void
index(TransportClient client, ESOrganization organization) {
IndexResponse response = client.prepareIndex(INDEX, TYPE, String.valueOf(organization.getId()))
.setSource(JSON.toJSONString(organization)).get();
System.out.println(response.getId());
}
public
static
void
getById(TransportClient client, String id) {
GetResponse response = client.prepareGet(INDEX, TYPE, id).get();
System.out.println(response.getSourceAsString());
}
public
static
void
deleteById(TransportClient client, String id) {
DeleteResponse response = client.prepareDelete(INDEX, TYPE, id).get();
System.out.println(response);
}
public
static
void
update(TransportClient client, ESOrganization organization)
throws
InterruptedException, ExecutionException {
UpdateRequest updateRequest =
new
UpdateRequest(INDEX, TYPE, String.valueOf(organization.getId()))
.doc(JSON.toJSONString(organization));
UpdateResponse response = client.update(updateRequest).get();
System.out.println(response);
}
public
static
void
multiGet(TransportClient client, String... ids) {
MultiGetResponse multiGetItemResponses = client.prepareMultiGet().add(INDEX, TYPE, ids).get();
for
(MultiGetItemResponse itemResponse : multiGetItemResponses) {
GetResponse response = itemResponse.getResponse();
if
(response.isExists()) {
String json = response.getSourceAsString();
System.out.println(json);
}
}
}
/**
* 复杂一点的搜索
* @param client
* @param searchReq
*/
public
static
void
search(TransportClient client, OrgSearchReq searchReq) {
BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();
if
(searchReq.getKeyword() !=
null
&& searchReq.getKeyword().length >
0
) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(String keyword : searchReq.getKeyword()) {
queryBuilder.should(QueryBuilders.matchQuery(
"name"
, keyword));
}
orgQueryBuilder.must(queryBuilder);
}
if
(!CollectionUtils.isEmpty(searchReq.getTypes())) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(Integer type : searchReq.getTypes()) {
queryBuilder.should(QueryBuilders.matchQuery(
"type"
, type));
}
orgQueryBuilder.must(queryBuilder);
}
if
(!CollectionUtils.isEmpty(searchReq.getIndustrialModeCodes())) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(Integer industrialMode : searchReq.getIndustrialModeCodes()) {
queryBuilder.should(QueryBuilders.matchQuery(
"industrialModeCodes"
, industrialMode));
}
orgQueryBuilder.must(queryBuilder);
}
if
(searchReq.getUpdatedAt() !=
null
&& searchReq.getUpdatedAt().length >
0
) {
if
(searchReq.getUpdatedAt()[
0
] !=
null
) {
orgQueryBuilder.must(QueryBuilders.rangeQuery(
"updatedAt"
).from(searchReq.getUpdatedAt()[
0
]));
}
if
(searchReq.getUpdatedAt().length ==
2
&& searchReq.getUpdatedAt()[
1
] !=
null
) {
orgQueryBuilder.must(QueryBuilders.rangeQuery(
"updatedAt"
).to(searchReq.getUpdatedAt()[
1
]));
}
}
if
(StringUtils.isEmpty(searchReq.getSortField())) {
searchReq.setSortField(
"updatedAt"
);
}
System.out.println(
"orgQueryBuilder: "
+orgQueryBuilder);
SearchResponse searchResponse = client.prepareSearch(INDEX).setTypes(TYPE)
.setQuery(orgQueryBuilder)
.addSort(searchReq.getSortField(), getSortOrder(searchReq.getSortType()))
.setFrom(searchReq.getOffset())
.setSize(searchReq.getSize())
.execute()
.actionGet();
List
new
ArrayList<>();
for
(SearchHit hit : searchResponse.getHits()) {
ESOrganization org = JSON.parseObject(hit.getSourceAsString(), ESOrganization.
class
);
orgs.add(org);
}
System.out.println(JSON.toJSONString(orgs,
true
));
}
private
static
SortOrder getSortOrder(String str) {
if
(StringUtils.isEmpty(str)) {
return
SortOrder.ASC;
}
for
(SortOrder sortOrder : SortOrder.values()) {
if
(sortOrder.name().equalsIgnoreCase(str)) {
return
sortOrder;
}
}
return
SortOrder.ASC;
}
private
static
ESOrganization getUpdateOrg() {
ESOrganization organization =
new
ESOrganization();
organization.setId(1l);
organization.setType(
1111111111
);
return
organization;
}
public
static
void
addIndex(TransportClient client) {
String[] orgNames = {
"小米科技有限责任公司"
,
"乐视网信息技术(北京)股份有限公司"
,
"网易(杭州)网络有限公司"
,
"阿里巴巴(中国)有限公司"
,
"上海希格斯网络科技有限公司"
,
"running man"
,
"chicken run"
,
"tom runs fast"
};
for
(
int
i =
0
; i< orgNames.length; i++) {
ESOrganization organization =
new
ESOrganization();
organization.setId(Long.valueOf(i+
1
));
organization.setName(orgNames[i]);
organization.setType(i *
1
);
organization.setIndustrialModeCodes(
new
Integer[]{
1
+i,
20
+i,
30
+i});
organization.setUpdatedAt(
new
Date());
index(client, organization);
}
}
public
static
void
main(String[] args)
throws
Exception {
TransportClient client =
null
;
try
{
client = buildClient();
createOrgMapping(client);
addIndex(client);
update(client, getUpdateOrg());
getById(client,
"1"
);
multiGet(client,
"2"
,
"3"
);
deleteById(client,
"8"
);
//索引创建成功之后1秒钟左右,才会变得可用
TimeUnit.SECONDS.sleep(
1
);
search(client, getSearchReq());
}
finally
{
closeClient(client);
}
}
private
static
OrgSearchReq getSearchReq() {
OrgSearchReq req =
new
OrgSearchReq();
req.setKeyword(
new
String[]{
"阿里巴巴"
,
"乐视"
});
req.setTypes(Arrays.asList(
3
));
req.setIndustrialModeCodes(Arrays.asList(
23
,
33
));
req.setUpdatedAt(
new
Date[]{
null
,
new
Date()});
return
req;
}
}
|
package
com.tch.test.elasticsearch.test;
import
java.util.Date;
public
class
ESOrganization {
private
Long id;
private
String name;
private
Integer type;
private
Integer[] industrialModeCodes;
private
Date updatedAt;
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
Integer getType() {
return
type;
}
public
void
setType(Integer type) {
this
.type = type;
}
public
Integer[] getIndustrialModeCodes() {
return
industrialModeCodes;
}
public
void
setIndustrialModeCodes(Integer[] industrialModeCodes) {
this
.industrialModeCodes = industrialModeCodes;
}
public
Date getUpdatedAt() {
return
updatedAt;
}
public
void
setUpdatedAt(Date updatedAt) {
this
.updatedAt = updatedAt;
}
}
|
package
com.tch.test.elasticsearch.test;
import
java.util.Date;
import
java.util.List;
public
class
OrgSearchReq {
private
String[] keyword;
private
List
private
List
private
Date[] updatedAt;
private
Integer page;
private
Integer size;
private
String sortField;
private
String sortType;
private
static
final
int
FIRST_PAGE =
1
;
private
static
final
int
PAGE_SIZE =
10
;
public
String[] getKeyword() {
return
keyword;
}
public
void
setKeyword(String[] keyword) {
this
.keyword = keyword;
}
public
List
return
types;
}
public
void
setTypes(List
this
.types = types;
}
public
List
return
industrialModeCodes;
}
public
void
setIndustrialModeCodes(List
this
.industrialModeCodes = industrialModeCodes;
}
public
Date[] getUpdatedAt() {
return
updatedAt;
}
public
void
setUpdatedAt(Date[] updatedAt) {
this
.updatedAt = updatedAt;
}
public
Integer getPage() {
if
(page ==
null
|| page <
0
) {
return
FIRST_PAGE;
}
return
page;
}
public
void
setPage(Integer page) {
this
.page = page;
}
public
Integer getSize() {
if
(size ==
null
|| size <
0
) {
return
PAGE_SIZE;
}
return
size;
}
public
void
setSize(Integer size) {
this
.size = size;
}
public
String getSortField() {
return
sortField;
}
public
void
setSortField(String sortField) {
this
.sortField = sortField;
}
public
String getSortType() {
return
sortType;
}
public
void
setSortType(String sortType) {
this
.sortType = sortType;
}
public
int
getOffset() {
return
(getPage() -
1
) * getSize();
}
}
|
4.demo解释:
上面的demo中,ESOrganization.java为存到es中的数据结构,OrgSearchReq.java为搜索的条件包装类。
简单的CRUD就不说了,下面主要说一下搜索(search)的部分:
搜索中使用了
BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();
|
在搜索条件复杂的情况下,我们只需要根据自己的需求使用 BoolQueryBuilder 的 must 和 should来添加 query 的条件,
这里的 must 类似 sql 中的 and, should 类似 sql 中的 or
例如上面的demo中:
BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();
if
(searchReq.getKeyword() !=
null
&& searchReq.getKeyword().length >
0
) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(String keyword : searchReq.getKeyword()) {
queryBuilder.should(QueryBuilders.matchQuery(
"name"
, keyword));
}
orgQueryBuilder.must(queryBuilder);
}
if
(!CollectionUtils.isEmpty(searchReq.getTypes())) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(Integer type : searchReq.getTypes()) {
queryBuilder.should(QueryBuilders.matchQuery(
"type"
, type));
}
orgQueryBuilder.must(queryBuilder);
}
if
(!CollectionUtils.isEmpty(searchReq.getIndustrialModeCodes())) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
for
(Integer industrialMode : searchReq.getIndustrialModeCodes()) {
queryBuilder.should(QueryBuilders.matchQuery(
"industrialModeCodes"
, industrialMode));
}
orgQueryBuilder.must(queryBuilder);
}
if
(searchReq.getUpdatedAt() !=
null
&& searchReq.getUpdatedAt().length >
0
) {
if
(searchReq.getUpdatedAt()[
0
] !=
null
) {
orgQueryBuilder.must(QueryBuilders.rangeQuery(
"updatedAt"
).from(searchReq.getUpdatedAt()[
0
]));
}
if
(searchReq.getUpdatedAt().length ==
2
&& searchReq.getUpdatedAt()[
1
] !=
null
) {
orgQueryBuilder.must(QueryBuilders.rangeQuery(
"updatedAt"
).to(searchReq.getUpdatedAt()[
1
]));
}
}
if
(StringUtils.isEmpty(searchReq.getSortField())) {
searchReq.setSortField(
"updatedAt"
);
}
|
对应到sql语句就是:
where
(
name
=
'xxx1'
or
name
=
'xxx2'
)
and
(type = xxx3
or
type = xxx4)
and
(industrialModeCodes = xxx5
or
industrialModeCodes = xxx6)
and
updatedAt > xxx7
and
updatedAt < xxx8
|
.addSort(searchReq.getSortField(), getSortOrder(searchReq.getSortType()))
.setFrom(searchReq.getOffset())
.setSize(searchReq.getSize())
|
对应的就是sql中的排序和分页。
但有一点不同就是
QueryBuilders.matchQuery(
"name"
, keyword)
|
和sql中的 name=xxx还有一点不同,因为前者会做分词,例如name为'小米有限公司' 经过分词之后,我们使用matchQuery搜索的时候,keyword输入 '小米' 也能搜到这个记录。
如果要完全等同,那就要使用:
QueryBuilders.termQuery(
"name"
,
"小米"
)
|
termQuery不会使用分词,而会使用精确匹配。
范围搜索则是使用rangeQuery:
QueryBuilders.rangeQuery(
"updatedAt"
).from(xxx)
|
5.查看索引的mapping:
http://localhost:9200/test/organization/_mapping?pretty
6.查看索引中的记录:
http://localhost:9200/test/organization/_search?pretty
7.es中index和type的区别
https://www.elastic.co/blog/index-vs-type
8.
2.0之后,filter已经和query合并:
9.elastic如何trouble shooting: