ElasticSearch01
一. 简介
Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
但是,Lucene只是一个库。想要 使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API
来隐藏Lucene的复杂性,从而让全文搜索变得简单。
Elasticsearch的中文网址:https://www.elastic.co/cn/products/elasticsearch
1.1 正向索引与倒排索引
正向索引与倒排索引,这是在搜索领域中非常重要的两个名词,正向索引通常用于数据库中,在搜索引擎领域使用的最多的就是倒排索引,我们根据如下两个网页来对这两个概念进行阐述:
html1
我爱我的祖国,我爱编程
html2:
我爱编程,我是个快乐的小码农
**正向索引: ** 假设我们使用mysql的全文检索,会对如上两句话分别进行分词处理,那么预计得到的结果如下:
我 爱 爱我 祖国 我的祖国 编程 爱编程 我爱编程
我 我爱 爱 编程 爱编程 我爱编程 快乐 码农 小码农
假设我们现在使用正向索引搜索 **编程
** 这个词,那么会到第一句话中去查找是否包含有 编程
这个关键词,如果有则加入到结果集中;第二句话也是如此。假设现在有成千上百个网页,每个网页非常非常的分词,那么搜索的效率将会非常非常低些。
**倒排索引: ** 倒排索引是按照分词与文档进行映射,我们来看看如果按照倒排索引的效果:
关键词 | 文档名 |
---|---|
我 | html1,html2,html3 |
爱 | html1,html2 |
爱我 | html1 |
我爱 | html2 |
祖国 | html1 |
我的祖国 | html1 |
编程 | html1,html2 |
我爱编程 | html1,html2 |
爱编程 | html1,html2 |
快乐 | html2 |
码农 | html2 |
小码农 | html2 |
如果采用倒排索引的方式搜索 编程
这个词,那么会直接找到关键词中查找到 编程
,然后查找到对应的文档,这就是所谓的倒排索引。正向索引是通过文档去查找单词,反向索引则是通过单词去查找文档。
倒排索引的优点还包括在处理复杂的多关键字查询时,可在倒排表中先完成查询的并、交等逻辑运算,得到结果后再对记录进行存取,这样把对文档的查询转换为地址集合的运算,从而提高查找速度
1.2 Elasticsearch概念以及产品
Elasticsearch中的索引的概念与数据库中索引的概念是完全不一样的,Elasticsearch中索引如果类比到数据库,那就是一个数据库名。
文档在Elasticsearch中就是具体的数据,类比到数据库中那就是一条记录。
二. Elasticsearch环境搭建
下载地址:https://www.elastic.co/cn/start,在下载页面我们需要下载 Elasticsearch和Kibana.
2.1 Elasticsearch的安装
2.1.1 单机版安装
下载后解压进入到bin目录下,双击elasticsearch.bat,即可启动。在浏览器输入:http://localhost:9200/ 是否安装成功,如下图所示:
2.1.2 集群安装 (了解)
Elasticsearch集群的安装非常的简单,只需要作一些简单的配置,修改配置文件 config/elasticsearch.yml。
本节将采用两台节点来配置集群,一台是Windows操作系统,另外一台是Linux操作系统,将Windows操作系统下的Elasticsearch节点作为主节点。两台服务器的IP地址如下:
操作系统 | IP | 节点类型 |
---|---|---|
Windows操作系统 | 192.168.43.240 | 主节点(master) |
Linux操作系统 | 192.168.223.139 | 从节点(Slave) |
主节点
- 修改C:\Windows\System32\drivers\etc\hosts文件,加入如下内容
192.168.43.240 master
- 修改Elasticsearch的config目录下的elasticsearch.yml文件,内容如下:
# 集群的名字
cluster.name: my-application
# 节点的名称
node.name: master
# 数据存放的位置
path.data: D:/elasticsearch-datas/to/data
# 日志存放的位置
path.logs: D:/elasticsearch-datas/to/logs
# 节点绑定的IP
network.host: 192.168.43.240
# 设置端口号
http.port: 9200
# 集群中所有的节点的ip地址
discovery.seed_hosts: ["192.168.43.240", "192.168.223.139"]
# 初始状态下集群中主节点的 node.name
cluster.initial_master_nodes: ["master"]
- 启动elasticsearch
从节点
- 创建elasticsearch用户,执行如下命令
useradd -m -s /bin/bash elasticsearch
- 给elasticsearch的主目录权限授予新创建的 elasticsearch 用户
chown -R elasticsearch /elasticsearch/
- 在 /etc/sysctl.conf 文件中加入如下内容
vm.max_map_count=262144 #加大虚拟内存空间,然后重启服务器
如果报以下错误,
max number of threads [3604] for user [elasticsearch] is too low, increase to at least [4096]
解决方案:修改 /etc/security/limits.conf 文件,在文件中加入如下内容:
* soft nproc 4096
* hard nproc 4096
- 在/etc/hosts目录下加入如下内容
192.168.43.240 master
- 修改Elasticsearch的config目录下的elasticsearch.yml文件,内容如下:
# 集群的名字
cluster.name: my-application
# 节点的名称
node.name: slave1
# 数据存放的位置
path.data: /elasticsearch-datas/to/data
# 日志存放的位置
path.logs: /elasticsearch-datas/to/logs
# 节点绑定的IP
network.host: 192.168.223.139
# 设置端口号
http.port: 9200
# 集群中所有的节点的ip地址
discovery.seed_hosts: ["192.168.43.240", "192.168.223.139"]
# 初始状态下集群中主节点的 node.name
cluster.initial_master_nodes: ["master"]
- 切换到elasticsearch用户,进入到elasticsearch的家目录下,执行如下命令
su - elasticsearch #切换用户
bin/elasticsearch #启动elasticsearch
集群监控
下载地址:https://github.com/lmenezes/cerebro/releases
直接双击cerebro家目录下的bin目录下的 cerebro.bat 即可启动,在浏览器地址栏访问:localhost:9000
在Node address输入:http://192.168.43.240:9200,然后点击 Connect 按钮
2.2 Kibana的安装
Kibana是世界上最受欢迎的开源日志分析平台ELK Stack中的“K” ,它为用户提供了一个工具,用于在存储于Elasticsearch集群中的日志数据进行检索,可视化和构建仪表板。
Kibana的核心功能是数据查询和分析。使用各种方法,用户可以搜索Elasticsearch中索引的数据,以查找其数据中的特定事件或字符串,以进行根本原因分析和诊断。基于这些查询,用户可以使用Kibana的可视化功能,允许用户使用图表,表格,地理图和其他类型的可视化以各种不同的方式可视化数据。
A. 下载后进入到家目录下的bin目录中,首先修改config目录下的kibana.yml文件,修改如下内容:
elasticsearch.hosts: ["http://192.168.43.240:9200", "http://192.168.223.139:9200"]
B. 进入bin目录下,双加 kibana.bat文件,在浏览器地址栏访问:http://localhost:5601
C. Kibana中我们使用最多的就是 Dev Tools工具,来进行所有命令的演示:
注:如上 GET _cat/indices
命令是查看所有的索引。
2.3 Logstash的安装
Logstash是一个开源的服务器端数据处理管道,可以同时从多个数据源获取数据,并对其进行转换,然后将其发送到你最喜欢的“存储”。创建于2009年,于2013年被elasticsearch收购。
Logstash的下载地址:https://www.elastic.co/cn/downloads/logstash
A.下载测试数据集,下载地址:http://files.grouplens.org/datasets/movielens/,在该网页中下载ml-latest.zip
下载后解压目录,将movies.csv文件拷贝到指定的目录下,例如:D:/logstash-datas/ 目录。
B. 进入到Logstash的解压目录,进入到config目录下,新建logstash.conf,文件内容如下:
input {
file {
path => "D:/logstash-datas/movies.csv"
start_position => "beginning"
sincedb_path => "D:/elasticsearch/logstash-7.4.2/db_path.log"
}
}
filter {
csv {
separator => ","
columns => ["id","content","genre"]
}
mutate {
split => { "genre" => "|" }
remove_field => ["path", "host","@timestamp","message"]
}
mutate {
split => ["content", "("]
add_field => { "title" => "%{[content][0]}"}
add_field => { "year" => "%{[content][1]}"}
}
mutate {
convert => {
"year" => "integer"
}
strip => ["title"]
remove_field => ["path", "host","@timestamp","message","content"]
}
}
output {
elasticsearch {
hosts => "http://localhost:9200"
index => "movies"
document_id => "%{id}"
}
stdout {}
}
C. 在命令行进入到logstash的bin目录下,输入如下命令启动Logstash:
logstash.bat -f D:\elasticsearch\logstash-7.4.2\config\logstash.conf
特别强调:路径中绝对不能有中文。
D. 在Kibana的Dev Tools中执行 GET _cat/indices
, 即可查看到movies数据集:
三. Elasticsearch的基本概念
3.1 索引、文档、类型
索引
Elasticsearch中的索引有多层的意思:a. 某一类文档的集合就构成了一个索引,类比到数据库就是一个数据库(或者数据库表);b.它还描述了一个动作,就是将某个文档保存在elasticsearch的过程也叫索引;c. 倒排索引。
文档
具体的一条数据,类比到数据库就是一条记录。
类型
在7.0之前,一个Index可以创建多个类型,从7.0开始,一个索引只能创建一个类型,也就是_doc
DBMS | Elasticsearch |
---|---|
database | Index |
table | type(在7.0之后type为固定值_doc) |
Row | Document |
Column | Field |
Schema | Mapping |
SQL | DSL(Descriptor Structure Language) |
四. RestAPI
查询所有的索引
GET _cat/indices
查询movies的信息
GET movies
查询movies的记录总数
GET movies/_count
查询movies的前几条数据
GET movies/_search
4.1 基本CRUD
A. 添加数据,没有指定ID, 系统会生成ID
POST user/_doc
{
"age": 10,
"firstName": "Will",
"lastName": "Smith"
}
然后查询:GET user/_search
B. 操作数据,指定ID,如果有对应的ID,就修改数据;如果没有对应的ID,就添加数据
POST user/_doc/1
{
"age": 20,
"firstName": "Roden",
"lastName": "Jhson"
}
C. 通过 _create
的方式,如果存在ID,就会报错
POST user/_create/2
{
"age": 40,
"firstName": "Douge",
"lastName": "Lee"
}
PUT user/_create/8
{
"age": 50,
"firstName":"Jacks",
"lastName": "Lily"
}
D. 查询指定ID的文档
GET user/_doc/1
E. 删除指定ID的文档
DELETE user/_doc/2Gxqc24BJqcwPamzqWgn
F. 指定ID,创建或者覆盖
PUT user/_doc/1
{
"age": 40,
"firstName": "Hello",
"lastName": "Lee"
}
G. 修改原有数据的结构
POST user/_update/1
{
"doc": {
"firstName":"Rodan",
"lastName": "Johson"
}
}
H.批量查询
GET _mget
{
"docs": [
{"_index":"movies", "_id":"104372"},
{"_index":"movies", "_id":"104374"}
]
}
I. 分页查询
GET movies/_search
{
"from": 0,
"size": 20
}
J. 批量插入(可以指定ID,也可以不指定ID)
POST user/_bulk
{"index":{"_id": 23}}
{"firstName":"Will", "lastName":"Smith", "mobile": "123455"}
{"index":{}}
{"firstName":"Lily", "lastName":"Bob", "mobile": "98765"}
4.2 URI查询
泛查询,就是不指定字段,全字段查找,如下查找所有字段中包含有2012的电影
GET movies/_search?q=2012
查询title中包含有2012的所有的电影(df是default field)
GET movies/_search?q=2012&df=title
或者
GET movies/_search?q=title:2012
查询title中包含有2012,取索引从10开始,共8条数据
GET movies/_search?q=title:2012&from=10&size=8
字符串判断查询:
# 查询titile中包含有Beautiful, Mind
GET movies/_search?q=title:Beautiful Mind
#查询title中包含有Beautiful, 并且年份大于2012
GET movies/_search?q=title:Beautiful AND year:>=2012
#查询titile中包含有Beautiful或者Mind
GET movies/_search?q=title:(Beautiful Mind)
GET movies/_search?q=title:(+Mind +Beautiful)
#查询title中包含有“Beautiful Mind”的所有的电影
GET movies/_search?q=title:"Beautiful Mind"
#查询title中既包含有Mind又包含有Beautiful的所有的电影,对先后顺序没有要求
GET movies/_search?q=title:(Mind AND Beautiful)
GET movies/_search?q=title:(+Mind AND +Beautiful)
#查询title中包含Mind但是不包含Beautiful的所有的电影
GET movies/_search?q=title:(Mind NOT Beautiful)
GET movies/_search?q=title:(Mind -Beautiful)
年份判断查询:
#查询2018年以后上映的电影
GET movies/_search?q=year:>=2018
#查询2012年到2017年上映的电影
GET movies/_search?q=year:(>=2012 AND <2018)
#查询2016年到2017年所有的电影,注意:必须以 ] 结尾
GET movies/_search?q=year:{2015 TO 2017]
正则判断查询:
#查询title中以Mi开头,中间包含一个字符,以d结尾的所有的电影
GET movies/_search?q=title:Mi?d
#查询title中以Min开头,后面为任何内容的电影
GET movies/_search?q=title:Min*
4.3 Request Body查询
在有些查询中,可能会用到各种特别复杂的查询,那么就需要使用Request Body查询。
A.以year的倒序排序,查询电影年份在 [2017, 2018]的数据, query只能单条件查询
GET movies/_search
{
"sort": [
{
"year": {
"order": "desc"
}
}
],
# query中只能有一个条件
"query": {
"range": {
"year": {
"gte": 2017,
"lte": 2018
}
}
}
}
B.以year的倒序排序,查询titile中包含有Beautiful或者Mind的数据, query只能单条件查询
GET movies/_search
{
"sort": [
{
"year": {
"order": "desc"
}
}
],
# query中只能有一个条件
"query": {
"match": {
"title": "Beautiful Mind"
}
}
}
C. 按照年份的倒序,分页查询
GET movies/_search
{
"sort": [
{
"year": {
"order": "desc"
}
}
],
"from": 0,
"size": 20
}
D. 短语匹配,查询title中包含有 “Beautiful Mind” 这个短语的的电影
GET movies/_search
{
"query": {
"match_phrase": {
"title": "Beautiful Mind"
}
}
}
E. 只查询部分列
GET movies/_search
{
"_source": ["title", "year"]
}
F. 多个条件查询,多条件查询必须使用bool
GET movies/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"year": {
"gte": 2017,
"lte": 2018
}
}
},
{
"match": {
"title": "Beautiful Mind"
}
}
]
}
}
}
G. 多字段同时匹配某些字符串
GET movies/_search
{
"query": {
"multi_match": {
"query": "beautiful mind Romance",
"fields": ["title", "genre"],
"type": "best_fields"
}
}
}
其中type的值有三个:
- most_fields:在多字段中匹配的越多排名越靠前
- best_fields: 能完全匹配的文档,排名越靠前。
- cross_fields: 查询越分散,排名越靠前。
H. query_string
的用法
GET movies/_search
{
"query": {
"query_string": {
"default_field": "title",
"query": "Beautiful Mind",
"default_operator": "AND" #不加默认是OR
}
}
}
GET movies/_search
{
"query": {
"query_string": {
"fields": ["title", "genre"],
"query": "Beautiful Mind",
"default_operator": "AND"
}
}
}
I. term
实现精准匹配,查询title为Beautiful Mind
的电影
GET movies/_search
{
"query": {
"term": {
"title.keyword": {
"value": "Beautiful Mind, A"
}
}
}
}
J. 多条件或者判断(should表示或者,must表示必须)
GET movies/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": "Beautiful Mind"
}
},
{
"range": {
"year": {
"gte": 2017,
"lte": 2018
}
}
}
]
}
}
}
K. 推荐搜索
GET movies/_search
{
"suggest": {
"title-suggest": {
"text": "minx",
"term": {
"field": "title",
"suggest_mode": "missing"
}
}
}
}
GET movies/_search
{
"suggest": {
"title-suggest": {
"text": "mine",
"term": {
"field": "title",
"suggest_mode": "popular"
}
}
}
}
GET movies/_search
{
"suggest": {
"title-suggest": {
"text": "minx",
"term": {
"field": "title",
"suggest_mode": "always"
}
}
}
}
所谓的推荐搜索就是当我们根据条件搜索的时候,因为单词的拼写错误,但是无法搜索出结果,那么Elasticsearch会给出一定的搜索建议,通过 sugguest
来实现。
我们说一下suggest_mode
的三种模式:missing
、popular
、always
**missing: ** 意思是当词典中没有找到对应的索引信息,才去推荐。
**popular: ** 意思是即使我们去搜索一个被索引了的单词,但是还是会去给我们推荐类似的但是出现频率很高的词。
**always: ** 无论在任何情况下,都给出推荐。
4.5 自动补全功能
Elasticsearch的自动补全功能是基于 suggest
来实现的,但是需要提前定义好需要进行搜索字段的mapping信息(mapping一旦创建好后是不能修改的)。
使用 GET movies 命令查看,定义mapping并执行,设置自动补全的属性的
type
必须是completion
,执行如下命令,先删除movies,再重新定义mapping
DELETE movies
PUT movies
{"mappings" : {
"properties" : {
"@version" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"genre" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"title" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"year" : {
"type" : "long"
}
}
}
}
C. 删除 logstash 的配置文件 db_path.log,然后再执行 logstash 命令,重新导入 movies 数据集
logstash.bat -f D:\elasticsearch\logstash-7.4.2\config\logstash.conf
D. 执行推荐 min表示前缀
GET movies/_search
{
"suggest": {
"title-suggest": {
"prefix": "min",
"completion": {
"field": "title",
"skip_duplicates": true #忽略重复
}
}
}
}
不足:completion这个推荐的方式只能是前缀查询,但是其查找速度极快。
E. Java代码实现自动补全功能,类似HTML中的 autocomplete 属性
elasticsearch与springboot整合实现步骤:
1.创建springboot项目,导入依赖( 注:不同版本的springboot对应elasticsearch版本也不同 )
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.创建配置类 ( 此次使用的是 springboot是2.3.X 版本,默认匹配7.6.X的elasticsearch )
package com.qf.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Bean
public RestHighLevelClient elasticsearchClient() {
// 两种方式获取 RestHighLevelClient(elasticsearch高端查询对象)
// spring官网
// final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
// .connectedTo("localhost:9200")
// .build();
// return RestClients.create(clientConfiguration).rest();
// elasticsearch官网
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
// 获取ElasticsearchRestTemplate模版对象(elasticsearch 6.x 使用的是ElasticsearchTemplate对象)
@Bean
public ElasticsearchRestTemplate elasticsearchRestTemplate() {
return new ElasticsearchRestTemplate(elasticsearchClient());
}
}
3.创建实体类
package com.qf.pojo;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import java.util.List;
@Document(indexName = "movies")
@Data
public class Movie {
private String id;
private String title;
private Integer year;
private List<String> genre;
}
4.创建MovieController查询所有
package com.qf.controller;
import com.qf.pojo.Movie;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("movie")
public class MovieController {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@GetMapping("findAll")
public List<Movie> findAll(){
//指定查询条件并获取查询对象
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(
new RangeQueryBuilder("year").from(2017, true)
.to(2018, true)
).build();
//获取查询命中结果封装到实体类对象中
SearchHits<Movie> searchHits =
elasticsearchRestTemplate.search(nativeSearchQuery, Movie.class, IndexCoordinates.of("movies"));
//获取查询命中的结果集
List<SearchHit<Movie>> searchHitList = searchHits.getSearchHits();
//创建集合并保存数据
ArrayList<Movie> list = new ArrayList<Movie>(searchHitList.size());
for(SearchHit<Movie> movieSearchHit:searchHits){
Movie movie=movieSearchHit.getContent();
list.add(movie);
}
//返回数据
return list;
}
}
5.浏览器访问controller进行测试
6.创建建议搜索MovieSuggestSearchContorller
package com.qf.controller;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@RestController
@RequestMapping("movie-suggest")
public class MovieSuggestSearchContorller {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@GetMapping("findAll")
public Object movieSuggest(String text){
// GET movies/_search
// {
// "suggest": {
// "title-suggest": {
// "prefix": "min",
// "completion": {
// "field": "title",
// "skip_duplicates": true
// }
// }
// }
// }
//推荐查询参数设置
CompletionSuggestionBuilder completionSuggestionBuilder =
new CompletionSuggestionBuilder("title")
.prefix(text).size(10);//设置输入推荐搜索的前缀值和显示数量
.skipDuplicates(true);//忽略重复
//设置suggest中标识的名字(任意名字,但需要和Suggestion中一致)
SuggestBuilder suggestBuilder = new SuggestBuilder()
.addSuggestion("suggest_movie", completionSuggestionBuilder);
//指定要查询的索引
SearchResponse response=elasticsearchRestTemplate.suggest(suggestBuilder, IndexCoordinates.of("movies"));
//获取Suggest对象
Suggest suggest = response.getSuggest();
//获取对应的建议搜索的结果
Suggest.Suggestion suggestion = suggest.getSuggestion("suggest_movie");
//创建集合来抓取建议搜索出来自动补全的结果集
Set<String> suggestResult = new HashSet<String>();
//获取结果集
List entries = suggestion.getEntries();
if(entries.size()>0 && entries!=null){
Object object = entries.get(0);
if( object instanceof CompletionSuggestion.Entry){
CompletionSuggestion.Entry entry = (CompletionSuggestion.Entry)object;
List <CompletionSuggestion.Entry.Option> options = entry.getOptions();
if(options!=null && options.size()>0){
for(CompletionSuggestion.Entry.Option option : options){
suggestResult.add(option.getText().toString());
}
}
}
}
return suggestResult;
}
}
访问浏览器:http://localhost:8080/movie-suggest/findAll?text=min 进行测试
导入静态资源,再次访问页面进行测试