搜索引擎:Elasticsearch

发布时间:2024年01月24日

(1)Elasticsearch和Solr的区别

Elasticsearch和Solr都是基于Lucene的分布式搜索引擎,它们具有高效、可扩展、分布式的特点。Elasticsearch主要适用于实时搜索、分析和数据可视化,Solr主要适用于企业级搜索。

Elasticsearch在大数据存储和实时搜索方面性能更优秀,Solr在文本分析、搜索语义理解等方面性能更强。Elasticsearch默认情况下集成了近实时搜索的功能,可以在几秒钟内从文档变更时就对新文档进行索引,而Solr需要手动设置使其能够支持实时搜索。

实例:假如有100万条数据需要搜索,使用Elasticsearch进行搜索,响应时间通常在毫秒或者数秒之间。而使用Solr进行搜索,其响应时间通常在数秒或者数十秒之间。

Elasticsearch和Solr在查询语法方面有所不同。Solr支持丰富的查询语法,能够满足更多复杂的查询需求;而Elasticsearch则采用了面向文档的查询方式,让用户能够更加方便地进行查询。同时,Elasticsearch支持通过API进行搜索以及通过Kibana进行数据可视化。

实例:假如有如下文本:“The quick brown fox jumps over the lazy dog”,我们可以用Solr进行复杂查询,如 “fox OR dog” 或 “The AND fox”,而在Elasticsearch中,我们可以更加直接地查询:“fox” 或者 “dog”。

Elasticsearch是一个开源项目,拥有庞大的社区。其API和插件的文档十分丰富,能够满足几乎所有的开发和使用需求。Solr也是一个开源项目,但是相较于Elasticsearch的社区,Solr的社区相对较小,在一些新特性的实现和开发方面可能会有所落后。

实例:如果你使用Elasticsearch中遇到了问题,你可以很容易地在论坛或者社区中找到支持和帮助,而如果你在使用Solr中遇到了问题,可能需要花费更长的时间来等待社区的响应。

(2)Elasticsearch配置

(1)【解压:elasticsearch-8.4.0】

配置:

elasticsearch.yml跨域配置

http.cors.enabled: true

http.cors.allow-origin: "*"

elasticsearch.yml访问不到9200解决

xpack.security.enabled: false

运行:elasticsearch.bat

访问:192.168.3.49:9200

(2)【解压:elasticsearch-head-master】

安装:nodejs

问题解决:

1.删除C:\Users\用户\下的.npmrc文件

2.npm cache clean --force

3.npm install -g cnpm --registery=https://registery.npm.taobao.org

运行:npm install / npm run start

访问:192.168.3.49:9100

(3)【解压:kibana-8.4.0】

配置:kibana.yml配置中文

? ? ? ? ? i18n.locale: "zh-CN"

启动:kibana.bat

(4)【解压:ik分词器D:\elasticsearch-8.4.0\plugins\ik】

(5)测试入门

最小切面

GET _analyze

{

? "analyzer": "ik_smart",

? "text": "中国共产党"

}

最细力度划分

GET _analyze

{

? "analyzer": "ik_max_word",

? "text": "中国共产党"

}

(6)自定义字典

【IKAnalyzer.cfg.xml】

<!--用户可以在这里配置自己的扩展字典 -->

<entry key="ext_dict">zhaoyang.dic</entry>

【zhaoyang.dic】

赵阳

赵哥

大连赵哥

(3)索引操作

(1)创建索引

ES 软件的索引可以类比为 MySQL 中表的概念,创建一个索引,类似于创建一个表

ES 不允许修改索引

# 创建索引

# PUT+索引名

PUT myindex

(2)查询指定索引

根据索引名称查询指定索引,如果查询到,会返回索引的详细信息

# 查询索引

# GET 索引名称

GET myindex

(3)查询所有索引

这里请求路径中的_cat 表示查看的意思,indices表示索引,所以整体含义就是查看当前 ES 服务器中的所有索引

# 查询索引

GET _cat/indices

(4)删除索引

删除索引

删除指定已存在的索引

# 删除索引

# DELETE+索引名称

DELETE test_inde

(4)文档操作

(1)创建文档

这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式

如果在创建数据时,指定唯一性标识,那么请求范式 POST,PUT 都可以

如果没有指定数据唯一性标识,只能使用 POST 请求

# 创建文档

# 创建文档

POST myindex/_doc/001

{

? "id" : 1001,

? "name" : "zhangsan",

? "age" : 30

}

POST myindex/_doc/002

{

? "id" : 1002,

? "name" : "lisi",

? "age" : 18

}

POST myindex/_doc/003

{

? "id" : 1004,

? "name" : "wangwu",

? "age" : 30

}

POST myindex/_doc/004

{

? "id" : 1004,

? "name" : "zhaoliu",

? "age" : 35

}

(2)查询文档

根据唯一性标识可以查询对应的文档

# 查询文档

GET myindex/_doc/001

(3)修改文档

修改文档本质上和新增文档是一样的,如果存在就修改,如果不存在就新增

# 修改文档

PUT myindex/_doc/001

{

? "age":20

}

(4)删除文档

删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)

# 删除文档

DELETE myindex/_doc/001

(5)查询所有文档

# 查询所有文档

GET myindex/_search

(5)数据搜索

(1)匹配查询文档

这里的查询表示文档数据中 JSON 对象数据中的 name 属性是lisi

GET myindex/_search

{

? "query": {

? "match": {

? ? "name": "lisi" #不会查出li si 此时查询关键字是lisi 而li si 的关键词是两个【li】【si】匹配不上

? }

? }

}

GET myindex/_search

{

? "query": {

? ? "term": {

? ? ? "name": {

? ? ? ? "value": "li si" #会查出li si 不会查出lisi? 此时关键字是li si

? ? ? }

? ? }

? }

}

(2)匹配查询字段

默认情况下,Elasticsearch 在搜索的结果中,会把文档中保存在_source 的所有字段都返回。如果我们只想获取其中的部分字段,我们可以添加_source 的过滤

GET myindex/_search

{

? "_source": ["name","age"],

? "query": {

? ? "term": {

? ? ? "name": {

? ? ? ? "value": "lisi"

? ? ? }

? ? }

? }

}

(3)组合"or"

GET myindex/_search

{

? "_source": ["name","age"],

? "query": {

? ? "bool": {

? ? ? "should": [

? ? ? ? {

? ? ? ? ? "match": {

? ? ? ? ? ? "name": "lisi"

? ? ? ? ? }

? ? ? ? },

? ? ? ? {

? ? ? ? ? "match": {

? ? ? ? ? ? "age": 35

? ? ? ? ? }

? ? ? ? }

? ? ? ]

? ? }

? }

}

(4)排序

GET myindex/_search

{

? "query": {

? ? "match_all": {}

? },

? "sort": [

? ? {

? ? ? "age": {

? ? ? ? "order": "desc"

? ? ? }

? ? }

? ]

}

(5)分页

GET myindex/_search

{

? "query": {

? ? "match_all": {}

? },

? "from": 0,

? "size": 2

}

(6)分组

GET myindex/_search

{

"aggs": {

? "ageGroup": {

? ? "terms": {

? ? ? "field": "age"

? ? }

? }

},

"size": 0 #只显示分组信息 不显示源信息

}

(7)平均值

GET myindex/_search

{

"aggs": {

? "ageAvg": {

? ? "avg": {

? ? ? "field": "age"

? ? }

? }

},

"size": 0

}

(8)求和

GET myindex/_search

{

"aggs": {

? "ageGroup": {

? ? "terms": {

? ? ? "field": "age"

? ? },

? ? "aggs": {

? ? ? "ageSum": {

? ? ? ? "sum": {

? ? ? ? ? "field": "age"

? ? ? ? }

? ? ? }

? ? }

? }

},

"size": 0

}

(9)TopN

GET myindex/_search

{

"aggs": {

? "Top3": {

? ? "top_hits": {

? ? ? "sort": [

? ? ? ? {

? ? ? ? ? "age": {

? ? ? ? ? ? "order": "desc"

? ? ? ? ? }

? ? ? ? }

? ? ? ? ],

? ? ? "size": 3

? ? }

? }

},

"size": 0

}

(6)SpringBoot+Elasticsearch

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>co.elastic.clients</groupId>

? ? ? ? ? ? <artifactId>elasticsearch-java</artifactId>

? ? ? ? ? ? <version>8.1.0</version>

? ? ? ? </dependency>

@Configuration

public class ElasticSearchConfig {

? ? @Bean

? ? public ElasticsearchClient elasticsearchClient(){

? ? ? ? RestClient client = RestClient.builder(new HttpHost("localhost", 9200,"http")).build();

? ? ? ? ElasticsearchTransport transport = new RestClientTransport(client,new JacksonJsonpMapper());

? ? ? ? return new ElasticsearchClient(transport);

? ? }

}

/**

*

* springBoot整合ElasticSearch8.x版本

*

*/

@SpringBootTest

class EsApplicationTests {

? ? @Autowired

? ? private ElasticsearchClient client;

? ? // 索引 CRUD

? ? // (1)增加index

? ? @Test

? ? public void createTest() throws IOException {

? ? ? ? CreateIndexResponse indexResponse = client.indices().create(c -> c.index("user"));

? ? }

? ? // (2)查询Index

? ? @Test

? ? public void queryTest() throws IOException {

? ? ? ? GetIndexResponse getIndexResponse = client.indices().get(i -> i.index("user"));

? ? }

? ? // (3)判断index是否存在

? ? @Test

? ? public void existsTest() throws IOException {

? ? ? ? BooleanResponse booleanResponse = client.indices().exists(e -> e.index("user"));

? ? ? ? System.out.println(booleanResponse.value());

? ? }

? ? // (4)删除index

? ? @Test

? ? public void deleteTest() throws IOException {

? ? ? ? DeleteIndexResponse deleteIndexResponse = client.indices().delete(d -> d.index("user"));

? ? ? ? System.out.println(deleteIndexResponse.acknowledged());

? ? }

? ? // Document CRUD

? ? // (1)插入document

? ? @Test

? ? public void addDocumentTest() throws IOException {

? ? ? ? User user = new User("user1", 10);

? ? ? ? IndexResponse indexResponse = client.index(i -> i

? ? ? ? ? ? ? ? .index("user")

? ? ? ? ? ? ? ? //设置id

? ? ? ? ? ? ? ? .id("1")

? ? ? ? ? ? ? ? //传入user对象

? ? ? ? ? ? ? ? .document(user));

? ? }

? ? // (2)更新Document

? ? @Test

? ? public void updateDocumentTest() throws IOException {

? ? ? ? UpdateResponse<User> updateResponse = client.update(u -> u

? ? ? ? ? ? ? ? ? ? ? ? .index("user")

? ? ? ? ? ? ? ? ? ? ? ? .id("1")

? ? ? ? ? ? ? ? ? ? ? ? .doc(new User("user2", 13))

? ? ? ? ? ? ? ? , User.class);

? ? }

? ? // (3)判断Document是否存在

? ? @Test

? ? public void existDocumentTest() throws IOException {

? ? ? ? BooleanResponse indexResponse = client.exists(e -> e.index("user").id("1"));

? ? ? ? System.out.println(indexResponse.value());

? ? }

? ? // (4)查询Document

? ? @Test

? ? public void getDocumentTest() throws IOException {

? ? ? ? GetResponse<User> getResponse = client.get(g -> g

? ? ? ? ? ? ? ? ? ? ? ? .index("user")

? ? ? ? ? ? ? ? ? ? ? ? .id("1")

? ? ? ? ? ? ? ? , User.class

? ? ? ? );

? ? ? ? System.out.println(getResponse.source());

? ? }

? ? // (5)删除Document

? ? @Test

? ? public void deleteDocumentTest() throws IOException {

? ? ? ? DeleteResponse deleteResponse = client.delete(d -> d

? ? ? ? ? ? ? ? .index("user")

? ? ? ? ? ? ? ? .id("1")

? ? ? ? );

? ? ? ? System.out.println(deleteResponse.id());

? ? }

? ? // (6)批量插入Document

? ? @Test

? ? public void bulkTest() throws IOException {

? ? ? ? List<User> userList = new ArrayList<>();

? ? ? ? userList.add(new User("user1", 11));

? ? ? ? userList.add(new User("user2", 12));

? ? ? ? userList.add(new User("user3", 13));

? ? ? ? userList.add(new User("user4", 14));

? ? ? ? userList.add(new User("user5", 15));

? ? ? ? List<BulkOperation> bulkOperationArrayList = new ArrayList<>();

? ? ? ? //遍历添加到bulk中

? ? ? ? for(User user : userList){

? ? ? ? ? ? bulkOperationArrayList.add(BulkOperation.of(o->o.index(i->i.document(user))));

? ? ? ? }

? ? ? ? BulkResponse bulkResponse = client.bulk(b -> b.index("user")

? ? ? ? ? ? ? ? .operations(bulkOperationArrayList));

? ? }

? ? // (7)查询

? ? @Test

? ? public void searchTest() throws IOException {

? ? ? ? SearchResponse<User> search = client.search(s -> s

? ? ? ? ? ? ? ? .index("user")

? ? ? ? ? ? ? ? //查询name字段包含hello的document(不使用分词器精确查找)

? ? ? ? ? ? ? ? .query(q -> q

? ? ? ? ? ? ? ? ? ? ? ? .term(t -> t

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .field("name")

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .value(v -> v.stringValue("hello"))

? ? ? ? ? ? ? ? ? ? ? ? ))

? ? ? ? ? ? ? ? //分页查询,从第0页开始查询3个document

? ? ? ? ? ? ? ? .from(0)

? ? ? ? ? ? ? ? .size(3)

? ? ? ? ? ? ? ? //按age降序排序

? ? ? ? ? ? ? ? .sort(f->f.field(o->o.field("age").order(SortOrder.Desc))),User.class

? ? ? ? );

? ? ? ? for (Hit<User> hit : search.hits().hits()) {

? ? ? ? ? ? System.out.println(hit.source());

? ? ? ? }

? ? }

}

文章来源:https://blog.csdn.net/u010605984/article/details/135739103
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。