ElasticSearch
对非结构化的数据进行结构化的搜索,针对文本数据的搜索。
2.全文检索的特点
1.相关度最高的排在前面
2.高亮显示
3.只处理文本,不处理语义
3.Lucene介绍
3.1 核心:索引创建、索引搜索
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fqoiPHwZ-1609928836866)(file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml1936\wps1.jpg)]
3.2 创建索引的原理
1.分词
2.词态、大小写转换
3.排序(自然排序)
4.合并(倒排)
5.形成倒排索引文档
3.3 maven导包
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.5.0</version>
</dependency>
4.问题
4.1 哪些字段需要索引以及分词?
需要创建倒排索引文档的、要进行关键字查询的需要索引,等值连接不需要分词(模糊查询需要),因为分词之后改变了本生的语义。
4.2 那些数据需要放到数据区?
1.列表需要展示的数据。
2.查询条件要用到的、列表又需要展示的数据。
5.ElasticSearch
5.1 es特点
分布式、方便集群、性能高(实时搜索)、支持各种语言、处理pb级别数据(1pb = 1024tb)、上手容易(屏蔽了lucene的复杂性)。
5.2 基本的增删改查
#添加
PUT /pethome/user/1
{
"id":1,
"name":"张家祥",
"address":"四川省成都市龙泉驿区"
}
PUT /pethome/user/2
{
"id":2,
"name":"zjx",
"address":"成都市龙泉驿区1"
}
#全局更新 直接覆盖以前的
PUT/pethome/user/2
{
"id":2,
"name":"zjx"
}
#局部更新
POST /pethome/user/2/_update
{
"doc":{
"address":"四川省成都市龙泉驿区1"
}
}
POST /pethome/user/1/_update
{
"doc":{
"id":1
}
}
#删除以前的employee
DELETE /pethome/employee/21
DELETE /pethome/employee/22
#删除索引库
DELETE /pethome
#查询
GET /pethome/user/1
#只查询资源
GET /pethome/user/1/_source
#组合查询
GET /pethome/user/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"张家祥"
}
}
],
"filter": {
"term":{
"id":1
}
}
}
},
"from":0,
"size":5,
"sort": [{"id": "asc"}]
}
#批量获取
GET /pethome/user/_mget
{
"ids":["1","2"]
}
5.3 dsl查询
match:标准查询(分词)
term:单词查询、等值查询(不分词)
range:范围查询
prefix:前缀查询
bool:组合条件查询
wildcard:通配符查询
5.4 安装分词器:ik分词器
POST _analyze
{
"analyzer":"ik_smart",
"text":"你好不好不好的挖掘的非"
}
#分词器安装后测试
5.5 映射
5.5.1 基本数据类型
① 基本字段类型
字符串:text(分词),keyword(不分词) StringField(不分词文本),TextFiled(要分词文本)
text默认为全文文本,keyword默认为非全文文本
数字:long,integer,short,double,float
日期:date
逻辑:boolean
{user:{“key”:value}}
{hobbys:[xxx,xx]}
② 复杂数据类型
对象类型:object
数组类型:array
地理位置:geo_point,geo_shape
5.5.2 简单映射
你可以向已有映射中增加字段,但你不能修改它。如果一个字段在映射中已经存在,这可能意味着那个字段的数据已经被索引。如果你改变了字段映射,那已经被索引的数据将错误并且不能被正确的搜索到。
#简单映射
PUT /zjx
POST /zjx/shop/_mapping
{
"shop":{
"properties":{
"name":{
"type":"text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
},
"price":{
"type":"integer"
}
}
}
}
#添加数据
PUT /zjx/shop/1
{
"name":"张三",
"price":111
}
GET /zjx/shop/1/_source
#对象的映射与索引
{
"properties": {
"id": {"type": "long"},
"girl": {
"properties":{
"name": {"type": "keyword"},
"age": {"type": "integer"}
}
}
}
}
5.5.3 全局模板
*默认方式:default(了解)*
PUT {indexName}
{
"mappings": {
"_default_": {
"_all": {
"enabled": false 关闭默认映射配置
}
},
"user": {
//指定自己的自定义配置
},
"dept": {
"_all": {
"enabled": true //启动默认配置
}
},
....
}
}
6.java操作es
// on startup
TransportClient client = null;
try {
/**
* 连接远程集群
*/
client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
/**
* 创建索引文档
*/
//批量创建数据
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
for(int i = 0;i<100;i++){
Map<String,Object> map = new HashMap<>();
map.put("id",i);
map.put("name", "唐花花"+i);
map.put("age", i+12);
map.put("sex", i/2==0?"男":"女");
IndexRequestBuilder indexRequestBuilder = client.prepareIndex("system1", "classes", i + "").setSource(map);
bulkRequestBuilder.add(indexRequestBuilder);
}
//批量添加
BulkResponse bulkItemResponses = bulkRequestBuilder.get();
//查询年龄是20-40岁,名字带有唐的女孩,每页为10条,第一页。年龄降序排序
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("system1").setTypes("classes");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(20).lt(40));
List<QueryBuilder> must = boolQueryBuilder.must();
must.add(QueryBuilders.matchQuery("name", "唐"));
//设置组合条件查询
searchRequestBuilder.setQuery(boolQueryBuilder);
//设置每页显示条数
searchRequestBuilder.setFrom(0);
//查看第几页
searchRequestBuilder.setSize(10);
//降序
searchRequestBuilder.addSort("age", SortOrder.fromString("desc"));
//得到查询条件后的结果数据
SearchResponse searchResponse = searchRequestBuilder.get();
SearchHit[] hits1 = searchResponse.getHits().getHits();
for (SearchHit searchHitFields : hits1) {
System.out.println(searchHitFields.getSource());
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
// on shutdown
client.close();