1 查询所有文档
1.1 http请求
1.1.1 查询所有索引库的文档url
post http://localhost:9200/_search
1.1.2 查询指定索引库指定类型下的文档url
post http://localhost:9200/xc_course/doc/_search
1.1.3 请求体json
{
"query": {
"match_all": {}
},
"_source" : ["name","studymodel"]
}
1.1.4 结果说明
took
:本次操作花费的时间,单位为毫秒。timed_out
:请求是否超时_shards
:说明本次操作共搜索了哪些分片hits
:搜索命中的记录hits.total
: 符合条件的文档总数
hits.hits
:匹配度较高的前N个文档hits.max_score
:文档匹配得分,这里为最高分_score
:每个文档都有一个匹配度得分,按照降序排列。_source
:显示了文档的原始内容。
1.2 javaAPI
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch {
@Autowired
private RestHighLevelClient client;
@Autowired
private RestClient restClient;
//搜索全部记录
@Test
public void testSearchAll() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式——搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}
}
2 分页查询
2.1 http请求
2.1.1 url
post http://localhost:9200/xc_course/doc/_search
2.1.2 请求体json
{
"from" : 0, "size" : 1,
"query": {
"match_all": {}
},
"_source" : ["name","studymodel"]
}
from
:表示起始文档的下标,从0开始。size
:查询的文档数量。
2.2 javaAPI
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch {
@Autowired
private RestHighLevelClient client;
@Autowired
private RestClient restClient;
//搜索分页查询
@Test
public void testSearchPage() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式——搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
int page = 1;
int size = 1;
//计算记录起始下标
int from = (page - 1) * size;
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}
}
3 TermQuery(不分词)
- 精确查询,在搜索时会整体匹配关键字,<font color="red">不再将关键字分词</font>。
3.1 http请求
3.1.1 url
post http://localhost:9200/xc_course/doc/_search
3.1.2 请求体json
{
"query": {
"term" : {
"name": "spring"
}
},
"_source" : ["name","studymodel"]
}
- 上边的搜索会查询
name
包括“spring”这个词的文档
3.2 javaAPI
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch {
@Autowired
private RestHighLevelClient client;
@Autowired
private RestClient restClient;
//精确查询 不分词
@Test
public void testTermQuery() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式——搜索全部
searchSourceBuilder.query(QueryBuilders.termQuery("name", "spring"));
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
int page = 1;
int size = 1;
//计算记录起始下标
int from = (page - 1) * size;
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}
}
4 根据id精确匹配
4.1 http请求
4.1.1 url
post: http://127.0.0.1:9200/xc_course/doc/_search
4.1.2 请求体json
{
"query": {
"ids" : {
"type" : "doc",
"values" : ["3", "4", "100"]
}
}
}
4.2 javaAPI
String[] split = new String[]{"1","2"};
List<String> idList = Arrays.asList(split);
searchSourceBuilder.query(QueryBuilders.termsQuery("_id", idList));
//或如下
String[] ids = new String[]{"1", "2"};
searchSourceBuilder.query(QueryBuilders.termsQuery("_id", ids));
5 matchQuery(分词)
match Query
即全文检索,它的搜索方式是<font color="red">先将搜索字符串分词</font>,再使用各各词条从索引中搜索。match query
与Term query
区别是match query
在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。
5.1 http请求
5.1.1 url
post http://localhost:9200/xc_course/doc/_search
5.1.2 请求体json
{
"query": {
"match" : {
"description" : {
"query" : "spring开发",
"operator" : "or"
}
}
}
}
query
:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用逗号分隔也可以不用。operator
:or
表示 只要有一个词在文档中出现则就符合条件,and
表示每个词都在文档中出现则才符合条件。
上边的搜索的执行过程是:
- 将“spring开发”分词,分为spring、开发两个词
- 再使用spring和开发两个词去匹配索引中搜索。
- 由于设置了
operator
为or
,只要有一个词匹配成功则就返回该文档。
{
"query": {
"match" : {
"description" : {
"query" : "spring开发框架",
"minimum_should_match": "80%"
}
}
}
}
- “spring开发框架”会被分为三个词:spring、开发、框架
- 设置
"minimum_should_match": "80%"
表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表示<font color="red">至少有两个词在文档中要匹配成功</font>。
5.2 javaAPI
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch {
@Autowired
private RestHighLevelClient client;
@Autowired
private RestClient restClient;
//分词 MatchQuery
@Test
public void testMatchQuery() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
//搜索方式
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式——matchQuery
searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架").operator(Operator.OR).minimumShouldMatch("70%"));//设置匹配占比
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
// int page = 1;
// int size = 1;
// //计算记录起始下标
// int from = (page - 1) * size;
// searchSourceBuilder.from(from);
// searchSourceBuilder.size(size);
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}
}
6 multiQuery
- 上边学习的
termQuery
和matchQuery
一次只能匹配一个Field
,multiQuery
一次可以匹配多个字段。 - 单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
6.1 http请求
6.1.1 url
post http://localhost:9200/xc_course/doc/_search
6.1.2 请求体json
{
"query": {
"multi_match" : {
"query" : "spring css",
"minimum_should_match": "50%",
"fields": [ "name", "description" ]
}
}
}
"fields": [ "name", "description" ]
表示分词的关键字要再name
和description
中进行匹配
{
"query": {
"multi_match" : {
"query" : "spring框架",
"minimum_should_match": "50%",
"fields": [ "name^10", "description" ]
}
}
}
"name^10"
:表示权重boost提升10倍,执行上边的查询,发现name中包括spring关键字的文档排在前边。通常关键字匹配上name
的权重要比匹配上description
的权重高,这里可以对name
的权重提升
6.2 javaAPI
//搜索方式——matchQuery
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "name", "description")
.minimumShouldMatch("50%")
.field("name", 10));//提高10倍权重
7 boolQuery 布尔查询
布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。三个参数:
must
:文档必须匹配must
所包括的查询条件,相当于 “AND”should
:文档应该匹配should
所包括的查询条件其中的一个或多个,相当于 "OR"must_not
:文档不能匹配must_not
所包括的该查询条件,相当于“NOT”
7.1 http请求
7.1.1 url
POST http://localhost:9200/xc_course/doc/_search
7.1.2 请求体json
{
"_source": ["name", "studymodel", "description"],
"from": 0,
"size": 1,
"query": {
"bool": {
"must": [{
"multi_match": {
"query": "spring框架",
"minimum_should_match": "50%",
"fields": ["name^10", "description"]
}
},
{
"term": {
"studymodel": "201001"
}
}
]
}
}
}
must
:表示必须,多个查询条件必须都满足。(通常使用must
)should
:表示或者,多个查询条件只要有一个满足即可。must_not
:表示非。
7.2 javaAPI
//布尔查询 boolMatchQuery
@Test
public void testBoolQuery() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
//搜索方式
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式 boolQuery
//multiQuery
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description")
.minimumShouldMatch("50%")
.field("name", 10);
//termQuery
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
//boolQuery
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(multiMatchQueryBuilder).must(termQueryBuilder);
searchSourceBuilder.query(boolQueryBuilder);
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}
8 Filter 过滤器
- 过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。
- 过虑器在布尔查询中使用,<font color="red">在搜索结果的基础上进行过滤</font>
8.1 http请求
8.1.1 url
POST http://localhost:9200/xc_course/doc/_search
8.1.2 请求体json
{
"_source": ["name", "studymodel", "description", "price"],
"query": {
"bool": {
"must": [{
"multi_match": {
"query": "spring框架",
"minimum_should_match": "50%",
"fields": ["name^10", "description"]
}
}],
"filter": [{
"term": {
"studymodel": "201001"
}
},
{
"range": {
"price": {
"gte": 60,
"lte": 100
}
}
}
]
}
}
}
range
:范围过滤,保留大于等于60 并且小于等于100的记录。term
:项匹配过滤,保留studymodel等于"201001"的记录。- <font color="red">注意:range和term一次只能对一个Field设置范围过滤。</font>
8.2 javaAPI
//过滤器 Filter
@Test
public void testFilter() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
//搜索方式
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式 boolQuery
//multiQuery
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description")
.minimumShouldMatch("50%")
.field("name", 10);
//boolQuery
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(multiMatchQueryBuilder);
//定义过滤器
boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(90).lte(100));
searchSourceBuilder.query(boolQueryBuilder);
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
}
9 sort 排序
- 可以在字段上添加一个或多个排序,支持在
keyword
、date
、float
等类型上添加,text
类型的字段上不允许添加排序。
9.1 http请求
9.1.1 url
POST http://localhost:9200/xc_course/doc/_search
9.1.2 请求体json
{
"_source": ["name", "studymodel", "description", "price"],
"query": {
"bool": {
"filter": [{
"range": {
"price": {
"gte": 0,
"lte": 100
}
}
}]
}
},
"sort": [{
"studymodel": "desc"
},
{
"price": "asc"
}
]
}
9.2 javaAPI
//排序 sort
@Test
public void testSort() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
//搜索方式
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式 boolQuery
//boolQuery
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//定义过滤器
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
//装载boolQuery
searchSourceBuilder.query(boolQueryBuilder);
//添加排序
searchSourceBuilder.sort("studymodel", SortOrder.DESC);
searchSourceBuilder.sort("price", SortOrder.ASC);
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
}
10 highlight 高亮显示
- 高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。
10.1 http请求
10.1.1 url
Post: http://127.0.0.1:9200/xc_course/doc/_search
10.1.2 请求体json
{
"_source": ["name", "studymodel", "description", "price"],
"query": {
"bool": {
"must": [{
"multi_match": {
"query": "开发框架",
"minimum_should_match": "50%",
"fields": ["name^10", "description"],
"type": "best_fields"
}
}],
"filter": [{
"range": {
"price": {
"gte": 0,
"lte": 100
}
}
}]
}
},
"sort": [{
"price": "asc"
}],
"highlight": {
"pre_tags": ["<tag1>"],
"post_tags": ["</tag2>"],
"fields": {
"name": {},
"description": {}
}
}
}
10.2 javaAPI
//高亮 highlight
@Test
public void testHighlight() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
//设置类型
searchRequest.types("doc");
//搜索源构建对象
//搜索方式
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索方式 boolQuery
//multiQuery
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发框架", "name", "description")
.minimumShouldMatch("50%")
.field("name", 10);
//boolQuery
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(multiMatchQueryBuilder);
//定义过滤器
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
//定义高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<tag>");
highlightBuilder.postTags("</tag>");
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
// highlightBuilder.fields().add(new HighlightBuilder.Field("description"));
searchSourceBuilder.highlighter(highlightBuilder);
//向搜索请求对象中设置搜索源
searchSourceBuilder.query(boolQueryBuilder);
//source源字段过滤
searchSourceBuilder.fetchSource(new String[] {"name", "studymodel", "price", "timestamp"}, new String[]{});
//设置搜索源 装载搜索条件
searchRequest.source(searchSourceBuilder);
//执行搜索
SearchResponse searchResponse = client.search(searchRequest);
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.totalHits;
//匹配度较高的前N个文档 不是总记录数
SearchHit[] searchHits = hits.getHits();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (SearchHit hit : searchHits) {
//文档主键
String id = hit.getId();
//原文档内同
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//源文档的name字段内容
String name = (String) sourceAsMap.get("name");
//高亮后的name字段内容
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields != null) {
//取出name高亮字段
HighlightField nameHighlight = highlightFields.get("name");
if (nameHighlight != null) {
Text[] fragments = nameHighlight.getFragments();
StringBuffer sb = new StringBuffer();
for (Text text : fragments) {
sb.append(text);
}
name = sb.toString();
}
}
System.out.println(name);
//由于前边设置了源文档的过滤,这时description是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//时间
Date date = dateFormat.parse((String) sourceAsMap.get("timestamp"));
}
}