本文分享本菜鸟的ElasticSearch笔记。
内容不是很多,也可能是我接触的不够深。
一起学习,一起进步 ~
本菜鸟QQ:599903582
笨鸟先飞,熟能生巧~
比心心 ~
提示:以下是本篇文章正文内容,下面案例可供参考
ES是一个基于RESTful web接口并且构建在Apache Lucence之上的开源分布式搜索引擎。分布式文档数据库,每个字段均可被索引,每个字符的数据均可被搜索,能够横向拓展至数以百计的服务器存储以及处理PB级的数据。
高可用 可拓展。
不支持事务。
文档是可以被索引的基本单位。
天然分片,天然集群
es 把数据分成多个shard,多个shard可以组成一份完整的数据,这些shard可以分布在集群中的各个机器节点中es 把数据分成多个shard。多个shard可以组成一份完整的数据,这些shard可以分布在集群中的各个机器节点中。
在实际运算过程中,每个查询任务提交到某一个节点,该节点必须负责将数据进行整理汇聚,再返回给客户端,也就是一个简单的节点上进行Map计算,在一个固定的节点上进行Reduces得到最终结果向客户端返回。
天然索引
ES 所有数据都是默认进行索引的,这点和mysql正好相反,mysql是默认不加索引,要加索引必须特别说明,ES只有不加索引才需要说明。而ES使用的是倒排索引和Mysql的B+Tree索引不同。
(极大的简化开发)
https://blog.csdn.net/tianyaleixiaowu/article/details/76149547
https://fscrawler.readthedocs.io/en/latest/index.html
(ES7中类型_type已经均为_doc, 这里的是之前版本的指令)
PUT test01 // 建立mapping,然后可以往里传数据 ,如果开始的时候没有指定则根据第一条数据进行推测
{
"mappings": {
"person":{
"properties":{
"id":{
"type":"keyword"
},
"name":{
"type":"text"
},
"age":{
"type":"integer"
}
}
}
}
}
PUT /test01/person/1 //往索引test01传数据,person为_type, 1 为 _id
{
"id":1,
"name":"xuchenglei",
"age":23
}
GET /test01/person/_search //查询 索引 test01 下 person类型的, 满足match匹配的数据
{
"query": {
"match": {
"name": "guomengyao"
}
}
}
GET /test01/person/_search
{
"query": {
"match": {
"_type": "person"
}
}
}
GET /test01/person/_search //得到索引test01下的person类型的所有数据
GET /_cat/nodes?v 查询各个节点状态
GET /_cat/indices?v 查询各个索引状态
GET /_cat/shard/xxxx 查询某个索引的分片情况
GET /_cat/indices?v //查询es中存在那些索引
PUT /movie_index 创建一个索引
DELETE /movie_index 删除一个索引,其实ES是不删除和修改任何数据的,只能其增加版本号
PUT /index/type/id // 插入式各字段的意思
GET movie_index/movie/1 直接用_id进行查询
修改-全部字段值替换 , 格式和新增一样,需要将字段全部写出赋值
修改-某一字段值替换:如下
POST movie_index/movie/3/_update
{
"doc": {
"doubanScore":"7.0"
}
}
DELETE movie_index/movie/3 删除一个document
按条件查询:如下
GET movie_index/movie/_search
{
"query":{
"match_all": {}
}
}
按分词查询:如下
GET movie_index/movie/_search
{
"query":{
"match": {"name":"red"}
}
}
按分词子属性查询:
GET movie_index/movie/_search
{
"query":{
"match": {"actorList.name":"zhang"}
}
}
按短语查询,不再利用分词技术,直接用短语在原始数据中匹配
GET movie_index/movie/_search
{
"query":{
"match_phrase": {"name":"operation red"}
}
}
fuzzy查询,无情精确匹配时,查询出非常接近的词
GET movie_index/movie/_search
{
"query":{
"fuzzy": {"name":"rad"}
}
}
filter过滤查询:查询后过滤
GET movie_index/movie/_search
{
"query":{
"match": {"name":"red"}
},
"post_filter":{
"term": {
"actorList.id": 3
}
}
}
filter : 查询前过滤
GET movie_index/movie/_search
{
"query":{
"bool":{
"filter":[ {"term": { "actorList.id": "1" }},
{"term": { "actorList.id": "3" }}
],
"must":{"match":{"name":"red"}}
}
}
}
filter 按照范围过滤:
GET movie_index/movie/_search
{
"query": {
"bool": {
"filter": {
"range": {
"doubanScore": {"gte": 8} // gt 大于 lt 小于 gte 大于等于 lte 小于等于
}
}
}
}
}
排序:
GET movie_index/movie/_search
{
"query":{
"match": {"name":"red sea"}
}
, "sort": [
{
"doubanScore": {
"order": "desc"
}
}
]
}
分页查询:
GET movie_index/movie/_search
{
"query": { "match_all": {} },
"from": 1,
"size": 1
}
指定查询字段:
GET movie_index/movie/_search
{
"query": { "match_all": {} },
"_source": ["name", "doubanScore"]
}
高亮显示:
GET movie_index/movie/_search
{
"query":{
"match": {"name":"red sea"}
},
"highlight": {
"fields": {"name":{} }
}
}
聚合:
GET movie_index/movie/_search
{
"aggs": {
"groupby_actor": {
"terms": {
"field": "actorList.name.keyword" // .keyword 使其不分词
}
}
}
}
字符串匹配查询
GET pv/_search
{
"query": {
"query_string": {
"default_field": "name",
"query": "076-97c8-24ca6147"
}
}
}
将会搜索name字段包含076-97c8-24ca6147的数据记录
es索引重建:
https://www.cnblogs.com/juncaoit/p/12815582.html
https://www.cnblogs.com/Ace-suiyuan008/p/9985249.html
https://github.com/medcl/elasticsearch-analysis-ik
https://github.com/bells/elasticsearch-analysis-dynamic-synonym/tree/master
(推荐下载下来看,有点多)
链接:https://github.com/MrXuSS/EsUtils
pom.xml
com.alibaba
fastjson
1.2.74
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.9.2
org.junit.jupiter
junit-jupiter
RELEASE
test
接口:
public interface EsClient {
/**
* 向es中创建文档索引, 若es中已存在改index,则插入失败。
*
* @param indexName 索引名称
* @param document id
* @param jsonStr json字符串, 要存入的数据
*/
public Boolean insertIndexWithJsonStr(String indexName, String document, String jsonStr);
/**
* 查询指定id下索引数据
*
* @param indexName 索引名称
* @param document id
* @return 返回得到的字符串, 没有返回null
* {"age":18,"id":1,"name":"xuchenglei"}
*/
public String queryIndex(String indexName, String document);
/**
* 查询索引下的所有数据
* @param indexName 索引名称
* @param startNum 开始的位置
* @param pageSize 分页的大小
* @return 数据的字符串, json格式; 没有返回null
* [{"name":"xuchenglei","id":1,"age":18},{"name":"xuchenglei","id":2,"age":18}]
*/
public String queryIndex(String indexName, Integer startNum, Integer pageSize);
/**
* 根据索引名称和id删除数据
* @param indexName 索引名称
* @param document id
* @return 是否删除成功; 索引不存在返货false
*/
public Boolean deleteIndex(String indexName, String document);
/**
* 删除indexName下的所有索引数据
* @param indexName 索引名称
* @return 删除是否成功。
*/
public Boolean deleteIndex(String indexName);
/**
* 判断索引是否存在
* @param indexName 索引名称
* @param document id
* @return true or false
*/
public Boolean isIndexExists(String indexName, String document);
/**
* 判断索引是否存在
* @param indexName 索引名称
* @return true or false
*/
public Boolean isIndexExists(String indexName);
/**
* 查询出所有的index
* @return 查询出所有的索引 Set
*/
public Set queryAllIndex();
/**
* 根据 index 和 id 更新 索引数据
* @param indexName 索引名称
* @param document id
* @param jsonStr 要更新的json
* @return 是否更新成功
*/
public Boolean updateIndex(String indexName, String document, String jsonStr);
/**
* index下的搜索
* @param field 属性
* @param text 值
* @param indexName 索引名称
* @param startNum 开始的位置
* @param pageSize 分页的大小
* @return 返回符合条件的值
*/
public String search(String field, String text, String indexName, Integer startNum, Integer pageSize);
/**
* 模糊查询, 并实现高亮
* @param field 属性名
* @param text value
* @param indexName 索引名
* @param startNum 开始的位置
* @param pageSize 分页大小
* @return json
*/
public String searchFuzzy(String field, String text, String indexName, Integer startNum, Integer pageSize);
/**
* 获取当前索引下的数据量
* @param indexName 索引名称
* @return 数据量条数
*/
public Long searchTotalHitsNum(String indexName);
/**
* 向es中创建文档索引, 若es中已存在改index,则插入失败。(异步)
*
* @param indexName 索引名称
* @param document id
*/
public void insertIndexWithJsonStrAsync(String indexName, String document, String jsonStr);
/**
* 根据索引名称和id删除数据,(异步)
* @param indexName 索引名称
* @param document id
*/
public void deleteIndexAsync(String indexName, String document);
/**
* 删除indexName下的所有索引数据,(异步)
* @param indexName 索引名称
*/
public void deleteIndexAsync(String indexName);
/**
* 根据 index 和 id 更新 索引数据 (异步)
* @param indexName 索引名称
* @param document id
* @param jsonStr 要更新的json
*/
public void updateIndexAsync(String indexName, String document, String jsonStr);
/**
* 索引重建(同步)。 注意:目标索引需要提前创建好
* @param fromIndex 重新索引的索引名
* @param destIndex 重新索引后的索引名
* @return 新创建的文档数
*/
public Long reIndex(String fromIndex, String destIndex);
/**
* 索引重建(异步)。注意:目标索引需要提前创建好
* @param fromIndex 重新索引的索引名
* @param destIndex 重新索引后的索引名
*/
public void reIndexAsync(String fromIndex, String destIndex);
}
实现单例模式:
/**
* 以单例模式提供EsClient实例
*/
public class EsServerManager {
private static EsServerManager instance;
private static RestHighLevelClient client;
private EsServerManager(){
HttpHost host = new HttpHost("192.168.2.201", 9200, "http");
client = new RestHighLevelClient(RestClient.builder(host));
}
public static synchronized EsServerManager getInstance(){
if(instance == null){
instance = new EsServerManager();
}
return instance;
}
public RestHighLevelClient getClient(){
return client;
}
}
API:
public class EsClientImpl implements EsClient{
private static Log log = LogFactory.getLog(EsClientImpl.class);
/**
* 向es中创建文档索引, 若es中已存在改index,则插入失败。
*
* @param indexName 索引名称
* @param document id
* @param jsonStr json字符串, 要存入的数据
*/
public Boolean insertIndexWithJsonStr(String indexName, String document, String jsonStr) {
Boolean indexExists = isIndexExists(indexName, document);
Boolean result = false;
if (!indexExists) {
IndexRequest indexRequest = new IndexRequest(indexName)
.id(document)
.source(jsonStr, XContentType.JSON);
IndexResponse indexResponse = null;
try {
indexResponse = EsServerManager.getInstance().getClient().index(indexRequest, RequestOptions.DEFAULT);
if(indexResponse.getResult() == DocWriteResponse.Result.CREATED){
result = true;
}
log.info(indexResponse.getIndex() + "--" + indexResponse.getId() + "--" + "插入成功");
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 查询指定id下索引数据
*
* @param indexName 索引名称
* @param document id
* @return 返回得到的字符串, 没有返回null
* {"age":18,"id":1,"name":"xuchenglei"}
*/
public String queryIndex(String indexName, String document) {
Boolean indexExists = isIndexExists(indexName, document);
if (indexExists) {
GetResponse getResponse = null;
GetRequest getRequest = new GetRequest(indexName, document);
try {
getResponse = EsServerManager.getInstance().getClient().get(getRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return getResponse == null ? null : getResponse.getSourceAsString().toString();
} else {
return null;
}
}
/**
* 查询索引下的所有数据
* @param indexName 索引名称
* @return 数据的字符串, json格式; 没有返回null
* [{"name":"xuchenglei","id":1,"age":18},{"name":"xuchenglei","id":2,"age":18}]
*/
public String queryIndex(String indexName, Integer startNum, Integer pageSize){
Boolean indexExists = isIndexExists(indexName);
if (indexExists) {
SearchResponse searchResponse = null;
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(indexName);
searchSourceBuilder.from(startNum);
searchSourceBuilder.size(pageSize);
searchRequest.source(searchSourceBuilder);
try {
searchResponse = EsServerManager.getInstance().getClient().search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
if(searchResponse != null){
SearchHit[] searchHits = searchResponse.getHits().getHits();
List
项目中也可以使用JestClient,支持这种JSON格式的查询方式:
在官方的RestClient 基础上,进行了简单包装的Jest客户端,而且该客户端也与springboot完美集成。
application.properties中加入
spring.elasticsearch.jest.uris=http://192.168.67.163:9200
org.springframework.boot
spring-boot-starter-data-elasticsearch
io.searchbox
jest
5.3.3
net.java.dev.jna
jna
4.5.1
@Autowired
JestClient jestClient;
@Test
public void testEs() throws IOException {
String query="{\n" +
" \"query\": {\n" +
" \"match\": {\n" +
" \"actorList.name\": \"张译\"\n" +
" }\n" +
" }\n" +
"}";
Search search = new Search.Builder(query).addIndex("movie_chn").addType("movie").build();
SearchResult result = jestClient.execute(search);
List> hits = result.getHits(HashMap.class);
for (SearchResult.Hit hit : hits) {
HashMap source = hit.source;
System.err.println("source = " + source);
}
}
ElasticSearch作为搜索引擎,在很多的搜索场景下应用的比较广泛。内容相对来说比较简单,但是有点杂,参考目录来看吧。
笨鸟先飞,熟能生巧 ~
本菜鸟QQ:599903582
比心心~