大家好,欢迎来到IT知识分享网。
日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)
搜索引擎:Elasticsearch、Solr、Lucene
- ELK中的ES:Elasticsearch
- SolrCloud 的搭建、使用
- Solr 高亮显示
- Spring Data Solr 使用
- Solr的安装与配置
- Solr 原理、API 使用
- Lucene 原理、API使用
- Lucene 得分算法
客户端库:使用您自己的编程语言与 Elasticsearch 交互
官网:https://www.elastic.co/cn/products/elasticsearch
Elasticsearch
将Elasticsearch注册到window的服务上,不用每次启动Elasticsearch
到Elasticsearch的bin目录下,执行以下命令:
服务安装:service install
服务启动:service start
服务停止:service stop
服务卸载:service remove
服务配置管理:service manager
ElasticSearch 插件安装 es head
elasticsearch-head插件
elasticsearch-head是一个elasticsearch的集群管理工具,它是完全由HTML5编写的独立网页程序,
你可以通过插件把它集成到es。或直接下载源码,在本地打开index.html运行它。
该工具的Git地址是: https://github.com/Aconex/elasticsearch-head
(推荐使用)方案二:下载解压
1.插件下载地址https://github.com/mobz/elasticsearch-head
2.安装方法:
将下载下的zip文件,解压缩到elasticsearch/plugins/head目录下
目录路径如下:elasticsearch-2.4.0/plugins/head/
3.启动elasticsearch:运行 bin目录下的 elasticsearch.bat 或 服务启动:service start
4.访问集群,浏览器地址栏输入 http://localhost:9200/_plugin/head/
ElasticSearch 基础 数据架构的主要概念
Windows安装CURL命令
1.使用方式一:cmd命令进入到curl.exe所在的目录下,执行curl --help测试
2.使用方式二:拷贝curl.exe文件到 C:\Windows\System32,然后就可以在DOS窗口中任意位置,使用curl命令了
3.使用方式三:配置环境变量(推荐)
在系统高级环境变量中,配置 CURL_HOME属性,值为 curl目录的绝对路径
path属性中的末尾添加值:;%CURL_HOME%;
curl命令
Elasticsearch 命令的一般格式是:REST VERB HOST:9200/index/doc-type
1.REST VERB 指的是RESTFUL风格的 PUT更新/创建、GET获取、DELETE删除
使用 curl -X 的动词前缀来明确指定 HTTP 方法:-XPUT、-XGET、-XDELETE。
2.HOST:9200 指的是 IP地址和端口
3.index 指的是 索引名称
4.doc-type 指的是 文档类型
Elasticsearch 创建一个索引
Elasticsearch 创建一个索引名blog,可在您的 shell 中运行以下命令:curl -XPUT "http://localhost:9200/blog/"
Elasticsearch 不需要指定文档的类型,比如不需要指定文档的id、title是什么类型,都可以创建索引,因为会自动创建对应的类型。
Lucene 需要指定文档的类型。
Elasticsearch 插入一个文档
1.要在 索引名/blog 下创建一个文档类型,然后把文档插入到该文档类型上。
要将包含 “Deck the Halls” 的文档插入索引中,可运行以下命令(将该命令和本教程的其他 CURL 命令都键入到一行中)
2.命令:curl -XPUT "http://localhost:9200/blog/article/1" -d "{"""id""":"""1""","""title""":"""Whatiselasticsearch"""}"
要创建的数据:"{"""id""": """1""", """title""": """Whatiselasticsearch"""}"
使用 PUT 动词将一个文档添加到 /article文档类型,并为该文档分配 ID 为1。URL 路径显示格式为:http://localhost:9200/index索引/doctype文档类型/ID唯一标识
curl命令查看文档
命令:curl -XGET "http://localhost:9200/blog/article/1"
格式:curl -XGET "http://localhost:9200/index索引/doctype文档类型/ID唯一标识"
Elasticsearch 使用您之前 PUT 进索引中的 JSON 内容作为响应:
curl命令更新文档
如果您认识到title字段写错了,并想将它更改为 Whatislucene 怎么办?可运行以下命令来更新文档:
因为此命令使用了相同的唯一 ID为1,所以该文档会被更新。
命令:curl -XPUT "http://localhost:9200/blog/article/1" -d "{"""id""":"""1""","""title""":"""Whatislucene"""}"
curl -XPOST "http://localhost:9200/blog/article/1" -d "{"""id""":"""1""","""title""":"""Whatislucene"""}"
格式:curl -XPUT http://localhost:9200/index索引/doctype文档类型/ID唯一标识
curl -XPOST http://localhost:9200/index索引/doctype文档类型/ID唯一标识
curl命令搜索文档
搜索文档:
基本查询,此查询比您运行来查找 “Get the Halls” 文档的简单 GET 要复杂一些。
文档 URL 有一个内置的 _search 端点用于此用途。
在标题中找到所有包含单词 lucene 的数据:curl -XGET "http://localhost:9200/blog/article/_search?q=title:'whatislucene'"(q 参数表示一个查询)
格式:curl -XGET "http://localhost:9200/index索引/doctype文档类型/_search?q=title:'查询内容'"
检索返回Json对象说明
1.took:该请求花了多少毫秒:
2.timed_out:该请求是否超时
3._shards:需要考虑 Elasticsearch 是一个集群化服务的事实
4.hits:total:它会告诉您获得了多少个结果
max_score:用于全文搜索
实际结果包含 fields 属性,因为您将 fields 参数添加到了查询中。
否则,结果中会包含 source,而且包含完整的匹配文档。_index、_type 和 _id 分别表示索引、文档类型、ID;
5._score 指的是全文搜索命中长度。这 4 个字段始终会在结果中返回。
curl命令删除文档
删除文档:
命令:curl -XDELETE "http://localhost:9200/blog/article/1"
格式:curl -XDELETE "http://localhost:9200/index索引/doctype文档类型/ID唯一标识"
删除索引
删除索引:
命令:curl -XDELETE "http://localhost:9200/blog"
格式:curl -XDELETE "http://localhost:9200/index索引"
使用Java API 操作客户端之创建TransportClient
运行一个 Java 应用程序和 Elasticsearch 时,有两种操作模式可供使用:
1.Node Client:应用程序实例将请求交给集群处理,然后集群分发给一个 Elasticsearch 节点来处理
2.Transport Client:将请求交给单独的一个 Elasticsearch 节点 来处理
1.pom.xml导入依赖
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2.ElasticSearch 服务默认端口 9300
Web 管理平台端口 9200
3.当直接在ElasticSearch 建立文档对象时,如果索引不存在的,默认会自动创建,映射采用默认方式 。
这里注意:如果连接到一个 Elasticsearch 集群,构建器可以接受多个地址。
在本课程中,您只有一个 localhost 节点 连接到端口 9300,而不是像之前在 REST API 的 CURL 中一样连接到 9200。
Java 客户端将会使用这个特殊端口,使用端口 9200将不起作用。
使用org.elasticsearch.client.Client连接服务器。所以任何操作都需要用上,我们把它的创建放置到@Before中,操作最后别忘记执行client.close()方法关闭。
4.Transport Client:将请求交给单独的一个 Elasticsearch 节点 来处理
private Client client;
//服务器为本机127.0.0.1;ElasticSearch 服务默认端口9300
client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300))
Node Client:应用程序实例将请求交给集群处理,然后集群分发给一个 Elasticsearch 节点来处理
Transport Client:将请求交给单独的一个 Elasticsearch 节点 来处理
新建文档,自动创建索引
方式一:拼装json的字符串
String json = "{" + "\"id\":\"1\"," +
"\"title\":\"基于Lucene的搜索服务器\"," +
"\"content\":\"它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口\""
+ "}"; // \" 表示转义为 "
// 创建索引
IndexResponse indexResponse = this.client.prepareIndex("index索引", "doctype文档类型", "ID唯一标识").setSource(json).execute().actionGet();
方式二:使用Map集合
Map<String, Object> json = new HashMap<String, Object>();
json.put("id", "2");
json.put("title", "基于Lucene的搜索服务器");
json.put("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
// 创建索引
IndexResponse indexResponse = this.client.prepareIndex("index索引", "doctype文档类型", "ID唯一标识").setSource(json).execute().actionGet();
方式三:使用 ElasticSearch的 帮助类XContentBuilder 来新建文档,创建json对象
XContentBuilder sourceBuilder = XContentFactory.jsonBuilder().startObject()
.field("id", 3)
.field("title", "ElasticSearch是一个基于Lucene的搜索服务器")
.field("content","它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口")
.endObject();
// 创建索引
IndexResponse indexResponse = this.client.prepareIndex("index索引", "doctype文档类型", "ID唯一标识").setSource(json).execute().actionGet();
搜索文档数据(单个索引)
private Client client;
//服务器为本机127.0.0.1;ElasticSearch 服务默认端口9300
client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300))
//单个索引
GetResponse response = client.prepareGet("index索引", "doctype文档类型", "ID唯一标识")
.setOperationThreaded(false) // 线程安全
.get();
搜索文档数据(多个索引)
private Client client;
//服务器为本机127.0.0.1;ElasticSearch 服务默认端口9300
client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300))
//多个索引
MultiGetResponse multiGetResponse = client.prepareMultiGet()
.add("index索引", "doctype文档类型", "ID唯一标识")
.add("index索引", "doctype文档类型", "ID唯一标识", "ID唯一标识", "ID唯一标识")
.add("index索引", "doctype文档类型", "ID唯一标识")
.get();
更新文档数据(3种方式):ID存在则更新,ID不存在则保存
更新方式一:
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index("要更新的 index索引");
updateRequest.type("要更新的 doctype文档类型");
updateRequest.id("要更新的 ID唯一标识"); //ID存在则更新,ID不存在则保存
updateRequest.doc(XContentFactory.jsonBuilder().startObject()
.field("title", "ElasticSearch是一个基于Lucene的搜索服务器")// 对没有的字段添加, 对已有的字段替换
.field("content","它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口")
.field("createDate", "2018-10-11").endObject());
UpdateResponse response = client.update(updateRequest).get();
client.close();
更新方式二:
//使用updateRequest对象 及 documents进行更新
UpdateResponse response = client.update(new UpdateRequest("index索引", "doctype文档类型", "ID唯一标识") //ID存在则更新,ID不存在则保存
.doc(XContentFactory.jsonBuilder().startObject()
.field("title", "什么是Elasticsearch").endObject()))// 对没有的字段添加, 对已有的字段替换
.get();
client.close();
更新方式三:
// IndexRequest("index索引", "doctype文档类型", "ID唯一标识"):设置查询条件, 根据ID查询。查找不到的话,则添加field所设置的数据
IndexRequest indexRequest = new IndexRequest("index索引", "doctype文档类型", "ID唯一标识")
.source(XContentFactory.jsonBuilder().startObject()
.field("id", 3)
.field("title", "搜索服务器")
.field("content","它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口")
.endObject());
// UpdateRequest("index索引", "doctype文档类型", "ID唯一标识"):设置更新条件, 根据ID查询,查找到的话,则更新下面的field所设置的数据
UpdateRequest upsert = new UpdateRequest("index索引", "doctype文档类型", "ID唯一标识")
.doc(XContentFactory.jsonBuilder().startObject()
.field("user", "李四")
.endObject())
.upsert(indexRequest);
client.update(upsert).get();
client.close();
第一次运行程序时,IndexRequest中所设置的ID查找不到,则添加IndexRequest中的field所设置的数据,并且因为UpdateRequest同样也查找不到所设置的ID,
即使这一次添加IndexRequest中的field所设置的数据有该ID,也不会执行UpdateRequest进行数据修改,只有在第二次运行程序时,IndexRequest中所设置的ID查找到了,
然后便会执行UpdateRequest进行数据修改
删除文档数据
写法一:DeleteResponse response = client.prepareDelete("index索引", "doctype文档类型", "ID唯一标识").get();
写法二:DeleteResponse response = client.prepareDelete("index索引", "doctype文档类型", "ID唯一标识").execute().actionGet();
IK分词器
在 Elasticsearch/plugins 目录下 创建 analysis-ik 文件夹,用于存储 Ik分词器的相关配置文件
把 Ik分词器根目录中 target/releases 文件夹中的 部分相关配置文件 拷贝到 Elasticsearch/plugins/analysis-ik 文件夹中
把 Ik分词器根目录中 target/releases/config 文件夹中的 部分相关配置文件 拷贝到 Elasticsearch/config 文件夹中
对 Elasticsearch/config 文件夹中的 elasticsearch.yml文件末尾添加:index.analysis.analyzer-ik.type: "ik"
注意:配置语句中 index.analysis.analyzer-ik.type: 和 "ik" 之间必须有一个空格
作用:该配置语句 表示 名称命名为ik,后续用到分词器的时候,使用ik这个名词。
对 Elasticsearch 配置完 ik 分词器之后,进行重启 Elasticsearch,或者点击 Elasticsearch/bin 目录中的 elasticsearch.bat 启动 Elasticsearch
http://localhost:9200/_analyze?analyzer=ik&pretty=true&text=中文内容
IK分词器 配置拓展词典:添加自定义单词
创建索引和删除索引
1.在ElasticSearch没有索引情况下 插入文档数据的话,默认创建索引和索引映射,但是无法使用ik分词器。
所以要想使用IK分词器,需要重新创建索引。
2.创建索引:client.admin().indices().prepareCreate("索引名").get();
3.删除索引:client.admin().indices().prepareDelete("索引名").get();
映射相关操作(创建映射并设置某个字段使用IK分词进行分词)
// 通过JSON配置数据的 类型/格式 和 映射关系
// field("store", "yes"):store的值为yes:表示该字段数据存储到索引库中
// field("analyzer", "ik"):analyzer的值为ik:表示该字段数据使用ik分词器进行分词
// id字段不需要设置分词器,因为id字段不需要进行分词。
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject() // 一个startObject必定对应一个endObject,两者组成一对 表示为一组数据
.startObject("文档类型")
.startObject("properties")
.startObject("字段id").field("type", "integer").field("store", "yes").endObject()
.startObject("字段title").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
.startObject("字段content").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
.endObject()
.endObject()
.endObject();
PutMappingRequest mapping = Requests.putMappingRequest("索引").type("文档类型").source(配置映射关系的JSON); //创建索引的同时设置映射关系对象
client.admin().indices().putMapping(映射关系对象).get();
条件查询QueryBuilders
1.可以使用REST API和简单查询或GET请求来搜索数据。
更改索引时,无论想执行的操作是更改映射还是文档索引化,都要用REST API向Elasticsearch发送JSON结构的数据。
2.类似地,如果想发送的不是一个简单的查询,仍然把它封装为JSON结构并发送给Elasticsearch。这就是所谓的查询DSL。
从更宏观的角度看,Elasticsearch支持两种类型的查询:基本查询和复合查询。
基本查询,如词条查询用于查询实际数据。
复合查询,如布尔查询,可以合并多个查询。
3.查询数据 主要依赖QueryBuilder对象 ,可以通过QueryBuilders获取各种查询(基于lucene)
QueryBuilders.boolQuery() 布尔查询,可以用来组合多个查询条件
QueryBuilders.fuzzyQuery() 相似度查询
QueryBuilders.matchAllQuery() 查询所有数据
QueryBuilders.regexpQuery() 正则表达式查询
QueryBuilders.termQuery() 词条查询
QueryBuilders.wildcardQuery() 模糊查询
1.使用SearchResponse获取,支持各种查询:
//搜索在elasticSearch中创建的文档对象
@Test
public void testSearch() throws Exception
{
// 搜索数据
// get() == execute().actionGet()
/* SearchResponse searchResponse = client.prepareSearch("一个或多个index索引")
.setTypes("一个或多个doctype文档类型")
.setQuery(QueryBuilders.matchAllQuery()).get();
*/
/**
* 1.第一种用法:ElasticSearch提供QueryBuileders.queryStringQuery("搜索内容")
* queryStringQuery查询方法:会对所有每个字段都会进行分词查询,实际进行的是对索引进行查询。
* 如果存储的中文数据使用了IK分词器进行分词并作为索引存储的话,那么此处查询操作便是对IK分词后的索引中文单词进行查询
*/
SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
.setQuery(QueryBuilders.queryStringQuery("全面")).get();
/**
* 2.第二种用法:ElasticSearch提供QueryBuileders.wildcardQuery("字段名","搜索内容")
* 比如只查询单个content字段的值中的内容,实际进行的是对索引进行查询。
* 使用QueryBuilders.wildcardQuery进行模糊查询,可加上通配符。比如:* 表示 多个任意字符。? 表示 单个任意字符。
* 如果存储的中文数据使用了IK分词器进行分词并作为索引存储的话,那么此处查询操作便是对IK分词后的索引中文单词进行查询
*/
SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
.setQuery(QueryBuilders.wildcardQuery("content", "*全?")).get();
/** 3.第三种用法:ElasticSearch提供QueryBuileders.termQuery("字段名","搜索内容")
* 比如只查询单个content字段的值中的内容,实际进行的是对索引进行查询。
* 如果存储的中文数据使用了IK分词器进行分词并作为索引存储的话,那么此处查询操作便是对IK分词后的索引中文单词进行查询
*/
SearchResponse searchResponse = client.prepareSearch("blog")
.setTypes("article")
.setQuery(QueryBuilders.termQuery("content", "全文")).get();
//--------------------------------------------------------
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
System.out.println("查询结果有:" + hits.getTotalHits() + "条"); //获取出查询结果有多少条记录数
Iterator<SearchHit> iterator = hits.iterator();//遍历查询结果中每条记录数据
while (iterator.hasNext())
{
SearchHit searchHit = iterator.next(); // 获取每个查询对象
System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
System.out.println("id:" + searchHit.getSource().get("id"));// 获取id字段的值
System.out.println("title:" + searchHit.getSource().get("title"));;// 获取title字段的值
System.out.println("content:" + searchHit.getSource().get("content"));;// 获取content字段的值
for (Iterator<SearchHitField> ite = searchHit.iterator(); ite.hasNext();)
{
SearchHitField next = ite.next();
System.out.println(next.getValues());
}
}
// 关闭连接
client.close();
}
文档相关操作(使用Jackson创建文档数据)
2.x 版本 引入jackson:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.1</version>
</dependency>
// 创建连接搜索服务器对象
Client client = TransportClient.builder().build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
// 描述json 数据 {id:xxx, title:xxx, content:xxx}
Article article = new Article();//自定义 JavaBean 类Article
article.setId(2);
article.setTitle("搜索工作其实很快乐");
article.setContent("我们希望我们的搜索解决方案要快");
ObjectMapper objectMapper = new ObjectMapper();
// 建立文档
client.prepareIndex("index索引", "doctype文档类型", "ID唯一标识" article.getId().toString()).setSource(objectMapper.writeValueAsString(article)).get();
// 关闭连接
client.close();
修改文档相关操作(使用Jackson修改文档数据)
方式一:使用prepareUpdate、prepareIndex都可以
Client client = TransportClient.builder().build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
Article article = new Article();//自定义 JavaBean 类Article
ObjectMapper objectMapper = new ObjectMapper();
client.prepareUpdate("index索引", "doctype文档类型", "ID唯一标识").setDoc(objectMapper.writeValueAsString(article)).get();
方式二:直接使用update
Client client = TransportClient.builder().build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
Article article = new Article();//自定义 JavaBean 类Article
ObjectMapper objectMapper = new ObjectMapper();
client.update(new UpdateRequest("index索引", "doctype文档类型", "ID唯一标识").doc(objectMapper.writeValueAsString(article))).get();
删除文档相关操作
方式一: prepareDelete
Client client = TransportClient.builder().build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
Article article = new Article();//自定义 JavaBean 类Article
client.prepareDelete("index索引", "doctype文档类型", "ID唯一标识").get();
方式二: 直接使用delete
Client client = TransportClient.builder().build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
Article article = new Article();//自定义 JavaBean 类Article
client.delete(new DeleteRequest("index索引", "doctype文档类型", "ID唯一标识").get();
各种查询
1.查询所有
// matchAllQuery()匹配所有文件
// match_all查询是Elasticsearch中最简单的查询之一。它使我们能够匹配索引中的所有文件。
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型").setQuery(QueryBuilders.matchAllQuery()).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
2.解析字符串查询QueryString
// 相比其他可用的查询,query_string查询支持全部的Apache Lucene查询语法
// 针对多字段的query_string查询
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型").setQuery(QueryBuilders.queryStringQuery("搜索内容")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
3.通配符查询(wildcardQuery)
// * 表示 匹配多个字符。? 表示 匹配1个字符
// 注意:避免搜索字符串以 * 开始, 会检索大量内容造成效率缓慢
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.wildcardQuery("字段名", "搜索内容 通配符 xxx*y?")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
4.词条查询(termQuery)
// 词条查询是Elasticsearch中的一个简单查询。它仅匹配在给定字段中含有该词条的文档,而且是确切的、未经分析的词条
// termQuery("key", obj) 完全匹配
// termsQuery("key", obj1, obj2..) 一次匹配多个值,只有有一个值是正确的,就可以查询出数据
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.termQuery("字段名", "搜索内容")).get();
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.termsQuery("字段名", "搜索内容1","搜索内容2")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
5.字段匹配查询
// matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
// match查询把query参数中的值拿出来,加以分析,然后构建相应的查询。使用match查询时,Elasticsearch将对一个字段选择合适的分析器,所以可以确定,
// 传给match查询的词条 将被建立索引时 相同的分析器处理。
// multiMatchQuery("text", "field1", "field2"..); 匹配多个字段, field有通配符进行
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.matchQuery("字段名", "搜索内容")).get();
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.multiMatchQuery( "搜索内容", "字段名1","字段名2")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
6.只查询ID(标识符查询)
// 标识符查询是一个简单的查询,仅用提供的标识符来过滤返回的文档。此查询针对内部的 _uid字段运行,所以它不需要启用_id字段
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.idsQuery().ids("ID值")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
7.相似度查询
// fuzzy查询是模糊查询中的第三种类型,它基于编辑距离算法来匹配文档
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.fuzzyQuery("字段名", "搜索内容")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
8.范围查询
// 范围查询使我们能够找到在某一字段值在某个范围里的文档,字段可以是 数值型,也可以是 基于字符串的
// includeLower(true):包含上界
// IncludeUpper(true):包含下界
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.rangeQuery("字段名").from("搜索内容1").to("搜索内容2").includeLower(true).includeUpper(true)).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
9.跨度查询
// 下面代码表示,从首字母开始,查询“字段名=搜索内容”,搜索内容前面的词可以为N个
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.spanFirstQuery(QueryBuilders.spanTermQuery("字段名", "搜索内容"), 跨度为N个字符的数字)).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
10.组合查询(复杂查询)
// must(QueryBuilders):AND
// mustNot(QueryBuilders):NOT
// should(QueryBuilders):OR
定义json:放置到Elasticsearch的插件中
{ "query" : { "bool" : { "must" : { "term" : { "title" : "elasticsearch" } },
"should" : { "range" : { "id" : { "from" : 1, "to" : 2 } } } } } }
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("字段名", "搜索内容")).
must(QueryBuilders.wildcardQuery("字段名", "搜索内容 通配符 xxx*y?"))).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
11.排序查询
SearchResponse searchResponse = client.prepareSearch("index索引").setTypes("doctype文档类型")
.setQuery(QueryBuilders.matchAllQuery())
.addSort("字段名", SortOrder.DESC).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
12.查询文档分页操作
// 批量向数据表 插入100条记录
@Test
public void createDocument100() throws Exception
{
// 创建连接搜索服务器对象
Client client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
//Mapper映射对象
ObjectMapper objectMapper = new ObjectMapper();
for (int i = 1; i <= 100; i++)
{
// JavaBean类 Article对象 描述json 数据
Article article = new Article();
article.setId(i);
article.setTitle(i + "搜索工作其实很快乐");
article.setContent(i + "我们希望我们的搜索解决方案要快");
// 建立文档:client.prepareUpdate("index索引", "doctype文档类型", "ID唯一标识").setSource(objectMapper.writeValueAsString(JavaBean类 Article对象)).get()
client.prepareIndex("blog2", "article", article.getId().toString()).setSource(objectMapper.writeValueAsString(article)).get();
}
// 关闭连接
client.close();
}
@Test
// 分页查询,查询所有的方法。searchRequestBuilder 的 setFrom【从0开始】 和 setSize【查询多少条记录】方法实现
public void testPage() throws Exception
{
// 创建连接搜索服务器对象
Client client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
// 搜索数据。client.prepareSearch("index索引").setTypes("doctype文档类型")
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2").setTypes("article")
.setQuery(QueryBuilders.matchAllQuery());
//setFrom():从第几条开始检索,默认是0。
//setSize():每页最多显示的记录数。默认每页10条记录
searchRequestBuilder.setFrom(20).setSize(20); // 此处为 查询第2页数据,每页20条
// get()方法 === execute().actionGet()方法
SearchResponse searchResponse = searchRequestBuilder.get();
printSearchResponse(searchResponse);
// 关闭连接
client.close();
}
13.查询结果高亮显示
查询结果之所以能高亮显示的原因:查看页面源码分析
@Test
// 高亮查询结果 处理 搜索
public void testHighLight() throws IOException
{
// 创建连接搜索服务器对象
Client client = TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
// 创建索引中的映射对象
ObjectMapper objectMapper = new ObjectMapper();
// 搜索数据。client.prepareSearch("index索引").setTypes("doctype文档类型").setQuery(QueryBuilders.termQuery("字段名", "列值"))
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2").setTypes("article").setQuery(QueryBuilders.termQuery("content", "搜索"));
// 配置应用高亮的高亮定义
searchRequestBuilder.addHighlightedField("content"); // 对content字段进行高亮
searchRequestBuilder.setHighlighterPreTags("<em>"); // 前置元素
searchRequestBuilder.setHighlighterPostTags("</em>");// 后置元素
// 设置摘要大小
searchRequestBuilder.setHighlighterFragmentSize(10);
// 进行查询,返回响应结果
SearchResponse searchResponse = searchRequestBuilder.get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
System.out.println("查询结果有:" + hits.getTotalHits() + "条"); // 查询结果数据条数
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext())
{
SearchHit searchHit = iterator.next(); // 每个查询对象
// 对结果的高亮片段做拼接处理,替换原有内容。将高亮处理后内容,替换原有内容 (原有内容,可能会出现显示不全 )
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField contentField = highlightFields.get("content"); // 对content字段进行高亮,因此先要获取content字段的数据
// 获取到原有内容并设置每个高亮显示的集中位置:fragment 就是高亮片段
Text[] fragments = contentField.fragments();
String content = "";
for (Text text : fragments)
{
content += text;//拼接高亮字段数据
}
// 将查询结果转换为自定义的JavaBean对象Article:objectMapper.readValue(查询对象searchHit.getSourceAsString(), JavaBean对象Article.class)
Article article = objectMapper.readValue(searchHit.getSourceAsString(), Article.class);
// 用高亮后内容,替换原有内容。如果值等于空,说明没有高亮的结果
if(content != null && !"".equals(content))
{
// 用高亮后内容,替换原有内容
article.setContent(content);
}
System.out.println(article);
}
// 关闭连接
client.close();
}
得分(加权)
1.随着应用程序的增长,提高搜索质量的需求也进一步增大。我们把它叫做搜索体验。我们需要知道什么对用户更重要,关注用户如何使用搜索功能。
这导致不同的结论,例如,有些文档比其他的更重要,或特定查询需强调一个字段而弱化其他字段。这就是可以用到加权的地方。
2.实现流程:在Query和Field中可以设置加权
例如:创建3条数据,通过加权影响我们的数据结果和得分
3.在Query的查询中定义加权
1.创建数据,Article中添加一个属性
public class Article
{
private Integer id;
private String title;
private String content;
private String comment;
}
2.重新创建索引和映射,创建文档
/**创建 索引*/
@Test
public void testCreateIndex_boost() throws Exception
{
// 创建索引:client.admin().indices().prepareCreate("index索引").get()
client.admin().indices().prepareCreate("blog1").get();
//关闭
client.close();
}
/**创建 映射*/
@Test
public void testCreateIndexMapping_boost() throws Exception
{
//构建json的数据格式,创建映射
XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
.startObject()
.startObject("article") // startObject("doctype文档类型")
.startObject("properties")
.startObject("id")//id字段
.field("type","integer").field("store", "yes")//使用默认的分词器,并把分词后的id索引值进行存储
.endObject()
.startObject("title") //使用IK分词器进行分词后的数据作为索引进行存储
.field("type","string").field("store", "yes").field("analyzer","ik")
.endObject()
.startObject("content")
.field("type","string").field("store", "yes").field("analyzer","ik")
.endObject()
.startObject("comment")
.field("type","string").field("store", "yes").field("analyzer","ik")
.endObject()
.endObject()
.endObject()
.endObject();
//Requests.putMappingRequest("index索引").type("doctype文档类型")
PutMappingRequest request = Requests.putMappingRequest("blog1").type("article").source(mappingBuilder);
client.admin().indices().putMapping(request).get();
//关闭
client.close();
}
/**创建文档*/
@Test
public void createDocument_boost() throws Exception
{
Article article = new Article();
//article.setId(1);
//article.setTitle("搜索引擎服务器"); // 有搜索
//article.setContent("基于restful的数据风格"); // 无搜索
//article.setComment("我们学习Elasticsearch搜索引擎服务器");// 有搜索
article.setId(2);
article.setTitle("什么是Elasticsearch"); // 无搜索
article.setContent("Elasticsearch搜索引擎服务器"); // 有搜索
article.setComment("Elasticsearch封装了lucene");// 无搜索
ObjectMapper objectMapper = new ObjectMapper();
String source = objectMapper.writeValueAsString(article);
System.out.println("source:"+source);
//client.prepareUpdate("index索引", "doctype文档类型", "ID唯一标识").setDoc(source).get();
IndexResponse indexResponse = client.prepareIndex("blog1", "article", article.getId().toString()).setSource(source).get();
// 获取响应的信息
System.out.println("索引名称:"+indexResponse.getIndex());
System.out.println("文档类型:"+indexResponse.getType());
System.out.println("ID:"+indexResponse.getId());
System.out.println("版本:"+indexResponse.getVersion());
System.out.println("是否创建成功:"+indexResponse.isCreated());
client.close();
}
3.测试
@Test
public void testQueryString_boost() throws Exception{
SearchResponse searchResponse = client.prepareSearch("blog1").setTypes("article")
.setQuery(QueryBuilders.queryStringQuery("搜索").field("content^10").field("title^5").field("comment"))
.get();
SearchHits hits = searchResponse.getHits();//获取数据的结果集对象,获取命中次数
// 显示数据
this.searchValue(hits);
//关闭
client.close();
}
@Test
public void testBoolQuery_boost() throws Exception{
SearchResponse searchResponse = client.prepareSearch("blog1").setTypes("article")
.setQuery(QueryBuilders.boolQuery().should(QueryBuilders.termQuery("title", "搜索").boost(5f))
.should(QueryBuilders.termQuery("content", "搜索").boost(10f)))
.get();
SearchHits hits = searchResponse.getHits();//获取数据的结果集对象,获取命中次数
// 显示数据
this.searchValue(hits);
//关闭
client.close();
}
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/14358.html