Elasticsearch

Elasticsearch

安装与使用

下载地址

ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D
logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D
kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D
ik分词器: https://github.com/medcl/elasticsearch-analysis-ik/releases
可视化插件es head: https://github.com/mobz/elasticsearch-head

ElasticSearch

  1. 解压ElasticSearch

  2. 解压es head

  3. 在es head目录下npm install

  4. 启动ElasticSearch

  5. 访问http://localhost:9200/查看是否启动

  6. 在es head目录下npm run start

  7. 访问http://localhost:9100/进行连接

  8. 出现跨域问题,在elasticsearch.yml配置文件中加入允许跨域

    http.cors.enabled: true
    http.cors.allow-origin: "*"
    
  9. 重新启动并连接

Kibana

  1. Kibana版本要与Elasticsearch一致

  2. 解压kibana

  3. 启动kibana

  4. 访问http://localhost:5601/

  5. 使用中文界面,在kibana.yml中添加

    i18n.locale: "zh-CN"
    
  6. 重新启动

ik分词器

  1. ik分词器版本要与Elasticsearch一致

  2. 解压至Elasticsearch的plugins文件夹下

  3. 启动Elasticsearch

  4. 通过命令可以看到一使用的插件

    elasticsearch-plugin list 
    
  5. 在kibana的控制台中测试

  6. 最少切分ik_smart

    GET _analyze
    {
      "analyzer": "ik_smart"
      , "text": "大头儿子"
    }
    //分词结果
    {
      "tokens" : [
        {
          "token" : "大头",
          "start_offset" : 0,
          "end_offset" : 2,
          "type" : "CN_WORD",
          "position" : 0
        },
        {
          "token" : "儿子",
          "start_offset" : 2,
          "end_offset" : 4,
          "type" : "CN_WORD",
          "position" : 1
        }
      ]
    }
    
  7. 最细粒度划分ik_max_word

    GET _analyze
    {
      "analyzer": "ik_max_word"
      , "text": "大头儿子"
    }
    //分词结果
    {
      "tokens" : [
        {
          "token" : "大头",
          "start_offset" : 0,
          "end_offset" : 2,
          "type" : "CN_WORD",
          "position" : 0
        },
        {
          "token" : "头儿",
          "start_offset" : 1,
          "end_offset" : 3,
          "type" : "CN_WORD",
          "position" : 1
        },
        {
          "token" : "儿子",
          "start_offset" : 2,
          "end_offset" : 4,
          "type" : "CN_WORD",
          "position" : 2
        }
      ]
    }
    
  8. 添加自定义词汇,在config目录下新建my.dic,加入自定义词汇"肚肚肚"

  9. 在IKAnalyzer.cfg.xml中加载自定义词典

    <entry key="ext_dict">my.dic</entry>
    
  10. 重启Elasticsearch

  11. 测试

    GET _analyze
    {
      "analyzer": "ik_smart"
      , "text": "肚肚肚"
    }
    //分词结果
    {
      "tokens" : [
        {
          "token" : "肚肚肚",
          "start_offset" : 0,
          "end_offset" : 3,
          "type" : "CN_WORD",
          "position" : 0
        }
      ]
    }
    

索引操作

新建索引 PUT

PUT /索引名/类型名/文档id
{请求体}

PUT /test1/type1/1
{
  #数据请求体
  "name": "pinked",
  "age": 7
}


PUT test2
{
  #规则请求体
  "mappings": {
    "properties": {
      "name": {
        "type": "text"		#text属性的字段会被分词器解析,keyword属性的字段不会
      },
      "age": {
        "type": "integer"
      },
      "birthday": {
        "type": "date"
      }
    }
  }
}

查询索引 GET

GET 索引名

GET test1

#查询结果
{
  "test1" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "long"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1596707098264",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "V4sVrZnuRS-ip_FHbSdupg",
        "version" : {
          "created" : "7080099"
        },
        "provided_name" : "test1"
      }
    }
  }
}

更新索引 PUT/POST

#通过PUT覆盖更新
PUT /test1/type1/1
{
  "name": "pinked",
  "age": 8
}

#结果
{
  "_index" : "test1",
  "_type" : "type1",
  "_id" : "1",
  "_version" : 2,   		#版本号会增加
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

#通过POST修改更新
POST /test1/_update/1
{
  "doc": {
    "age": "9"
  }
}

#结果
{
  "_index" : "test1",
  "_type" : "type1",
  "_id" : "1",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

删除索引 DELETE

DELETE test1

文档操作

#添加数据
PUT /pinked/user/1
{
  "name": "野原新之助",
  "age": 5
}
PUT /pinked/user/2
{
  "name": "野比大雄",
  "age": 10
}
PUT /pinked/user/3
{
  "name": "胖虎",
  "age": 10
}

#简单搜索
GET /pinked/user/2

#条件搜索_search?q=k:v
GET /pinked/user/_search?q=age:10

复杂查询

GET /pinked/user/_search
{
  "query": {
    "match": {
      "name": "野"
    }
  },
  "_source": ["name"],		#选择字段
  "sort": [					#排序
      {
        "age": {
          "order": "desc"
      }
    }
  ],
  "from": 0,				#分页
  "size": 1
}

#多条件查询
GET /pinked/user/_search
{
  "query": {
    "bool": {
      "must": [				#must同and, should同or
        {
          "match": {
            "name": "野"
          }
        },
        {
          "match": {
            "age": 5
          }
        }
      ]
    }
  }
}

#
GET /pinked/user/_search
{
  "query": {
    "bool": {
      "must": [				
        {
          "match": {
            "name": "野"
          }
        }
      ],
      "filter": {			#过滤器
        "range": {			#范围
          "age": {
            "gt": 3,		#大于3
            "lte": 5		#小于等于5
          }
        }
      }
    }
  }
}

#结果高亮
GET /pinked/user/_search
{
  "query": {
    "match": {
      "name": "野 大"
    }
  },
  "highlight": {
  	#"pre_tags": "<span style='color:red'>",  	#自定义标签前缀
    #"post_tags": "</span>", 					#自定义标签后缀
    "fields": {
      "name": {}			#高亮的字段,会被<em>标签包裹
    }
  }
}

与SpringBoot整合

新建一个springboot项目

相关依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
spring data中导入的es依赖版本是7.6.2的,可以自定义导入的版本,尽量与本地的es版本保持一致
<properties>
    <java.version>1.8</java.version>
    <!--自定义es依赖版本至7.8.0-->
    <elasticsearch.version>7.8.0</elasticsearch.version>
</properties>

配置文件

@Configuration
public class ElasticSearchClientConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
        return client;
    }
}

获得客户端

@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;

索引操作

//创建索引
@Test
void createIndex() throws IOException {
    CreateIndexRequest request = new CreateIndexRequest("my_index");
    //执行请求
    CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
    System.out.println(response.isAcknowledged());
}

//判断索引是否存在
@Test
void isIndexExists() throws IOException {
    GetIndexRequest request = new GetIndexRequest("my_index");
    boolean b = client.indices().exists(request, RequestOptions.DEFAULT);
    System.out.println(b);
}

//删除索引
@Test
void deleteIndex() throws IOException {
    DeleteIndexRequest request = new DeleteIndexRequest("my_index");
    AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
    System.out.println(response.isAcknowledged());
}

文档操作

//添加文档
@Test
void insertDoc() throws IOException {
    User user = new User("野原新之助", 5);
    IndexRequest request = new IndexRequest("my_index");
    //设置规则
    request.id("1")
            .timeout(TimeValue.timeValueSeconds(5))
            .source(JSON.toJSONString(user), XContentType.JSON);
    IndexResponse response = client.index(request, RequestOptions.DEFAULT);
    System.out.println(response.toString());
    System.out.println(response.status());
}

//判断文档是否存在
@Test
void isDocExists() throws IOException {
    GetRequest request = new GetRequest("my_index", "1");
    boolean b = client.exists(request, RequestOptions.DEFAULT);
    System.out.println(b);
}

//获取文档
@Test
void getDoc() throws IOException {
    GetRequest request = new GetRequest("my_index", "1");
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    System.out.println(response);
    System.out.println(response.getSourceAsString());
}

//更新文档
@Test
void updateDoc() throws IOException {
    User user = new User("野比大雄", 10);
    UpdateRequest request = new UpdateRequest("my_index", "1");
    request.timeout(TimeValue.timeValueSeconds(5))
            .doc(JSON.toJSONString(user), XContentType.JSON);
    UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
    System.out.println(response.status());
}

//删除文档
@Test
void deleteDoc() throws IOException {
    DeleteRequest request = new DeleteRequest("my_index", "1");
    request.timeout(TimeValue.timeValueSeconds(5));
    DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
    System.out.println(response.status());
}

//批量操作
@Test
void BulkRequest() throws IOException {
    List<User> userList = new ArrayList<>();
    userList.add(new User("野原新之助", 5));
    userList.add(new User("野比大雄", 10));
    userList.add(new User("刚田武", 10));
    BulkRequest request = new BulkRequest();
    request.timeout(TimeValue.timeValueSeconds(10));
    for (int i = 0; i < userList.size(); i++) {
        request.add(new IndexRequest("my_index")
                .id("" + i + 1)
                .source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
    }
    BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
    System.out.println(responses.hasFailures());
}

//查询
@Test
void search() throws IOException {
    SearchRequest request = new SearchRequest("my_index");
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    TermQueryBuilder query = QueryBuilders.termQuery("username.keyword", "野原新之助");
    sourceBuilder.query(query);
    sourceBuilder.timeout(TimeValue.timeValueSeconds(10));
    request.source(sourceBuilder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsString());
    }
}
原文地址:https://www.cnblogs.com/pinked/p/13633063.html