感谢这篇文章,让我一下就看懂了,牛皮:
搜索引擎技术系列教材 (十七)- elasticsearch - elastic search 教程;什么是,ElasticSearch,和,,Solr,一样的,,ElasticSearch,也是基于,Lucene进行了封装,提供了更为便利的访问和调用;关于JDK版本,至少使用JDK8版本,请下载JDK8或者更高版本:,下载以及配置JDK环境;下载,教程使用的ElasticSerach是截至目前,...https://how2j.cn/k/search-engine/search-engine-start/1691.html?p=42551========================================================================
学习了Lucene, 现在开始学习ElasticSearch。
以连接数据库为类比:Lucene 就相当于JDBC,是基本的用法。
ElasticSearch就相当 Mybatis, 方便开发人员配置,访问和调用。
使用ElasticSearch有个可视化工具叫做kibana,方便通过ElasticSearch往dictionary中插入数据、查询与关键字相关的数据。
ElasticSearch和kibana下载地址,包含win版的,中文网比官网快多了:
下载中心 - Elastic 中文社区https://elasticsearch.cn/download/下载完成后解压后点击bin文件夹下的产品名字.bat即可启动。
==========================================================
先启动ElasticSearch后启动kibana,打开浏览器访问地址http://localhost:5601/app/kibana#/dev_tools/console?_g=()
输入 GET /_cat/health?v 查看kibana是否正常
=====================================================
通过kibana连接es实现CRUD
增加索引 PUT /how2java?pretty
查询刚才新建的索引 GET /_cat/indices?v
删除索引 DELETE /how2java?pretty
再次查询索引发现刚才新建的索引index没了
===============================================================
分词器:
分词器指的是搜索引擎如何使用关键字进行匹配,如 入门 中的关键字:护眼带光源。 如果使用like,那么%护眼带光源%,匹配出来的结果就是要么全匹配,要不都不匹配。
而使用分词器,就会把这个关键字分为 护眼,带,光源 3个关键字,这样就可以找到不同相关程度的结果了。
要分开中文,需要给es安装插件IK,下载地址
在ES安装目录的bin文件夹下输入
elasticsearch-plugin install 刚才的地址
我这7.15.2的中文分词器插件如下
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.15.2/elasticsearch-analysis-ik-7.15.2.zip
分词器插件安装成功
重启es和kibana后测试中文分词成功
GET _analyze
{
"analyzer":"ik_max_word",
"text":"护眼带光源"
}
增加文档
PUT /how2java/product/1?pretty
{
"name": "蜡烛"
}
其中的product在elastic search里是type的概念,相当于数据库里的表,这里就相当于向 product 表里插入了一条数据。
获取文档
GET /how2java/product/1?pretty
修改文档
POST /how2java/product/1/_update?pretty
{
"doc": { "name": "蓝色蜡烛" }
}
删除文档
DELETE /how2java/product/1?pretty
批量插入
POST _bulk
{"index":{"_index":"how2java","_type":"product","_id":10001}}
{"code":"540785126782","price":398,"name":"房屋卫士自流平美缝剂瓷砖地砖专用双组份真瓷胶防水填缝剂镏金色","place":"上海","category":"品质建材"}
{"index":{"_index":"how2java","_type":"product","_id":10002}}
{"code":"24727352473","price":21.799999237060547,"name":"艾瑞泽手工大号小号调温热熔胶枪玻璃胶枪硅胶条热溶胶棒20W-100W","place":"山东青岛","category":"品质建材"}
{"index":{"_index":"how2java","_type":"product","_id":10003}}
查看索引how2j下面的所有数据
GET /how2java/_search
{
"query": { "match_all": {} }
}
可以观察到,通过kibana对ES存储在内存中的数据进行CRUD的格式,完全就是REST风格的HTTP请求。
===============================================================
通过javaAPI连接es实现CRUD
那么如何通过 Java api实现对Elastic Search的管理??步骤见下文
搜索引擎技术系列教材 (二十六)- elasticsearch - JavaAPI
项目结构及代码如下:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Elasticsearch2java</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<elasticsearch.version>7.3.1</elasticsearch.version>
<jackson.version>2.9.4</jackson.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
实体类
package com.javacodegeeks.example;
public class Person {
private String personId;
private String name;
private String number;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPersonId() {
return personId;
}
public void setPersonId(String personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return String.format("Person{personId='%s', name='%s', number='%s}", personId, name, number);
}
}
main方法直接往es里添加数据
package com.javacodegeeks.example;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class Application {
//The config parameters for the connection
private static final String HOST = "localhost";
private static final int PORT_ONE = 9200;
private static final int PORT_TWO = 9201;
private static final String SCHEME = "http";
private static RestHighLevelClient restHighLevelClient;
private static ObjectMapper objectMapper = new ObjectMapper();
private static final String INDEX = "persondata";
private static final String TYPE = "_doc";
/**
* 与elastic数据库实现连接使用单例模式
* Implemented Singleton pattern here
* so that there is just one connection at a time.
*
* @return RestHighLevelClient
*/
private static synchronized RestHighLevelClient makeConnection() {
if (restHighLevelClient == null) {
restHighLevelClient = new RestHighLevelClient(
RestClient.builder(
new HttpHost(HOST, PORT_ONE, SCHEME),
new HttpHost(HOST, PORT_TWO, SCHEME)));
}
return restHighLevelClient;
}
// 断开连接
private static synchronized void closeConnection() throws IOException {
restHighLevelClient.close();
restHighLevelClient = null;
}
// 插入一条
public static Person insertPerson(Person person) {
person.setPersonId(UUID.randomUUID().toString());
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("name", person.getName());
dataMap.put("number", person.getNumber());
IndexRequest indexRequest = new IndexRequest(INDEX).id(person.getPersonId()).source(dataMap);
try {
IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
e.getDetailedMessage();
} catch (IOException ex) {
ex.getLocalizedMessage();
}
/*
// The following is another way to do it
// More information https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-document-index.html
String id = UUID.randomUUID().toString();
person.setPersonId(id);
IndexRequest request = new IndexRequest(INDEX);
request.id(id);
String jsonString = "{" +
"\"name\":" + "\"" + person.getName() + "\"" +
"}";
System.out.println("jsonString: " + jsonString);
request.source(jsonString, XContentType.JSON);
try {
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
e.getDetailedMessage();
} catch (java.io.IOException ex){
ex.getLocalizedMessage();
}
*/
return person;
}
private static Person getPersonById(String id) {
GetRequest getPersonRequest = new GetRequest(INDEX, id);
GetResponse getResponse = null;
try {
getResponse = restHighLevelClient.get(getPersonRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.getLocalizedMessage();
}
return getResponse != null ?
objectMapper.convertValue(getResponse.getSourceAsMap(), Person.class) : null;
}
private static SearchResponse searchAll() {
SearchRequest searchRequest = new SearchRequest(INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
final SearchRequest source = searchRequest.source(searchSourceBuilder);
SearchResponse response = null;
try {
response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.getLocalizedMessage();
}
return response;
}
private static SearchResponse searchTerm() {
SearchRequest searchRequest = new SearchRequest(INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("name.keyword", "张三"));
final SearchRequest source = searchRequest.source(searchSourceBuilder);
SearchResponse response = null;
try {
response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.getLocalizedMessage();
}
return response;
}
private static SearchResponse matchQuery() {
Map<String, String> params = Collections.emptyMap();
/*
String queryString = "{" +
" \"size\": 4, " +
" \"query\": {" +
" \"match\": {" +
" \"name\": \"张三\" " +
"}";
*/
SearchRequest searchRequest = new SearchRequest(INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("name", "张三"));
final SearchRequest source = searchRequest.source(searchSourceBuilder);
SearchResponse response = null;
try {
response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.getLocalizedMessage();
}
return response;
}
private static Person updatePersonById(String id, Person person) {
UpdateRequest updateRequest = new UpdateRequest(INDEX, id)
.fetchSource(true); // Fetch Object after its update
try {
String personJson = objectMapper.writeValueAsString(person);
updateRequest.doc(personJson, XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
return objectMapper.convertValue(updateResponse.getGetResult().sourceAsMap(), Person.class);
} catch (JsonProcessingException e) {
e.getMessage();
} catch (IOException e) {
e.getLocalizedMessage();
}
System.out.println("Unable to update person");
return null;
}
private static void deletePersonById(String id) {
DeleteRequest deleteRequest = new DeleteRequest(INDEX, TYPE, id);
try {
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.getLocalizedMessage();
}
}
public static void main(String[] args) throws IOException {
//与elasticSearch数据库连接
makeConnection();
//存入两条数据
Person person = new Person();
person.setName("张三");
System.out.println("Inserting a new Person with name " + person.getName());
person.setNumber("111111");
person = insertPerson(person);
System.out.println("Person inserted --> " + person);
person = new Person();
person.setName("姚明");
System.out.println("Inserting a new Person with name " + person.getName());
person.setNumber("222222");
person = insertPerson(person);
System.out.println("Person inserted --> " + person);
//将姚明的名字改成李四
person.setName("李四");
System.out.println("Changing name to " + person.getName());
updatePersonById(person.getPersonId(), person);
System.out.println("Person updated --> " + person);
//查询所有
System.out.println("Searching for all documents");
SearchResponse response = searchAll();
System.out.println(response);
//查询
System.out.println("Searching for a term");
response = searchTerm();
System.out.println(response);
//查找张三
System.out.println("Match a query");
response = matchQuery();
System.out.println(response);
//查找李四
System.out.println("Getting 李四");
Person personFromDB = getPersonById(person.getPersonId());
System.out.println("Person from DB --> " + personFromDB);
//删除两个人的记录
// System.out.println("Deleting " + person.getName());
// deletePersonById(personFromDB.getPersonId());
// System.out.println("Person " + person.getName() + " deleted!");
//关闭连接
// closeConnection();
}
}
如上,数据已经加入ES中了,实际是在内存中,ES一关闭就会丢失。此时我们可以通过kibana查看刚才插入的数据,也可以直接控制台查看。kibana查看所有数据结果如下
===================================================================
根据关键词匹配
比如我想查询刚才存进去的数据中name与“算命张实诚”这句话中相关的记录,根据之前插入的数据,应该会显示出所有包含“张”字的记录,如下,还可以看到匹配度0.69和
看一下分词器将我们那句话,也就是关键词分成了什么。如下分成了三个词,所以之前查询的的时候就会拿着这三个词去存的数据中匹配,将name中包含了“张”的返回给我。
============================================================
感谢这篇文章,让我一下就看懂了,牛皮: