文章目錄
歡迎訪問筆者個人技術博客:http://rukihuang.xyz/
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(不分詞)
- 精確查詢,在搜索時會整體匹配關鍵字,不再將關鍵字分詞。
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
即全文檢索,它的搜索方式是先將搜索字符串分詞,再使用各各詞條從索引中搜索。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,表示至少有兩個詞在文檔中要匹配成功。
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 過濾器
- 過慮是針對搜索的結果進行過慮,過慮器主要判斷的是文檔是否匹配,不去計算和判斷文檔的匹配度得分,所以過慮器性能比查詢要高,且方便緩存,推薦儘量使用過慮器去實現查詢或者過慮器和查詢共同使用。
- 過慮器在布爾查詢中使用,在搜索結果的基礎上進行過濾
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"的記錄。- 注意:range和term一次只能對一個Field設置範圍過濾。
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"));
}
}