前言
本文是對 23個最有用的Elasticseaerch檢索技巧
一文提到的ES檢索技巧進行 Java API 的簡單實現,但僅限於簡單實現,並不考慮包括引數校驗,異常處理,日誌處理,安全等問題,僅供參考
程式碼見 UsefullESSearchSkill ,原查詢語句請對照原文
執行環境
JDK version : 10.0.2
gradle version : 4.7
Elasticsearch version : 6.3.2
IDEA version : 2018.2
執行前請啟動 ES 例項,並修改 application.properties
檔案中的ES配置
類介紹
實體類 Book
注意:日期 publish_date 的型別設定為 String 是避免 Java 到 ES 之間複雜的轉換工作,在ES中該欄位仍然被識別為 date 型別
public class Book {
public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private String id;
private String title;
private List<String> authors;
private String summary;
private String publish_date;
private Integer num_reviews;
private String publisher;
...
}
複製程式碼
公共類 Constants
定義了一些常用的常量
public class Constants {
// 欄位名
public static String ID = "id";
public static String TITLE = "title";
public static String AUTHORS = "authors";
public static String SUMMARY = "summary";
public static String PUBLISHDATE = "publish_date";
public static String PUBLISHER = "publisher";
public static String NUM_REVIEWS = "num_reviews";
public static String TITLE_KEYWORD = "title.keyword";
public static String PUBLISHER_KEYWORD = "publisher.keyword";
// 過濾要返回的欄位
public static String[] fetchFieldsTSPD = {ID, TITLE, SUMMARY, PUBLISHDATE};
public static String[] fetchFieldsTA = {ID, TITLE, AUTHORS};
public static String[] fetchFieldsSA = {ID, SUMMARY, AUTHORS};
public static String[] fetchFieldsTSA = {ID, TITLE, SUMMARY, AUTHORS};
public static String[] fetchFieldsTPPD = {ID, TITLE, PUBLISHER, PUBLISHDATE};
public static String[] fetchFieldsTSPN = {ID, TITLE, SUMMARY, PUBLISHER, NUM_REVIEWS};
// 高亮
public static HighlightBuilder highlightS = new HighlightBuilder().field(SUMMARY);
}
複製程式碼
公共類 EsConfig
建立 ES 客戶端例項,ES 客戶端用於與 ES 叢集進行互動
@Configuration
public class EsConfig {
@Value("${elasticsearch.cluster-nodes}")
private String clusterNodes;
@Value("${elasticsearch.cluster-name}")
private String clusterName;
@Bean
public Client client() {
Settings settings = Settings.builder().put("cluster.name", clusterName)
.put("client.transport.sniff", true).build();
TransportClient client = new PreBuiltTransportClient(settings);
try {
if (clusterNodes != null && !"".equals(clusterNodes)) {
for (String node : clusterNodes.split(",")) {
String[] nodeInfo = node.split(":");
client.addTransportAddress(new TransportAddress(InetAddress.getByName(nodeInfo[0]), Integer.parseInt(nodeInfo[1])));
}
}
} catch (UnknownHostException e) {
}
return client;
}
}
複製程式碼
資料獲取工具類 DataUtil
這裡的資料也就是 23個最有用的ES檢索技巧
文中用於實驗的4條資料
public class DataUtil {
public static SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd");
/**
* 模擬獲取資料
*/
public static List<Book> batchData() {
List<Book> list = new LinkedList<>();
Book book1 = new Book("1", "Elasticsearch: The Definitive Guide", Arrays.asList("clinton gormley", "zachary tong"),
"A distibuted real-time search and analytics engine", "2015-02-07", 20, "oreilly");
Book book2 = new Book("2", "Taming Text: How to Find, Organize, and Manipulate It", Arrays.asList("grant ingersoll", "thomas morton", "drew farris"),
"organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization",
"2013-01-24", 12, "manning");
Book book3 = new Book("3", "Elasticsearch in Action", Arrays.asList("radu gheorge", "matthew lee hinman", "roy russo"),
"build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms",
"2015-12-03", 18, "manning");
Book book4 = new Book("4", "Solr in Action", Arrays.asList("trey grainger", "timothy potter"), "Comprehensive guide to implementing a scalable search engine using Apache Solr",
"2014-04-05", 23, "manning");
list.add(book1);
list.add(book2);
list.add(book3);
list.add(book4);
return list;
}
public static Date parseDate(String dateStr) {
try {
return dateFormater.parse(dateStr);
} catch (ParseException e) {
}
return null;
}
複製程式碼
公共查詢工具類 CommonQueryUtils
對執行完ES查詢請求後的資料進行解析
public class CommonQueryUtils {
public static Gson gson = new GsonBuilder().setDateFormat("YYYY-MM-dd").create();
/**
* 處理ES返回的資料,封裝
*/
public static List<Book> parseResponse(SearchResponse searchResponse) {
List<Book> list = new LinkedList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
// 用gson直接解析
Book book = gson.fromJson(hit.getSourceAsString(), Book.class);
list.add(book);
}
return list;
}
/**
* 解析完資料後,構建 Response 物件
*/
public static Response<List<Book>> buildResponse(SearchResponse searchResponse) {
// 超時處理
if (searchResponse.isTimedOut()) {
return new Response<>(ResponseCode.ESTIMEOUT);
}
// 處理ES返回的資料
List<Book> list = parseResponse(searchResponse);
// 有shard執行失敗
if (searchResponse.getFailedShards() > 0) {
return new Response<>(ResponseCode.FAILEDSHARDS, list);
}
return new Response<>(ResponseCode.OK, list);
}
...
}
複製程式碼
資料準備
BulkTests
建立索引,以及使用 bulk API 批量插入資料
@RunWith(SpringRunner.class)
@SpringBootTest
public class BulkTests {
// 在Test中 Autowired需要引入包 org.elasticsearch.plugin:transport-netty4-client:6.3.2,否則異常找不到Transport類
@Autowired
private Client client;
@Value("${elasticsearch.bookIndex}")
private String bookIndex;
@Value("${elasticsearch.bookType}")
private String bookType;
private Gson gson = new GsonBuilder().setDateFormat("YYYY-MM-dd").create();
/**
* 建立索引,設定 settings,設定mappings
*/
@Test
public void createIndex() {
int settingShards = 1;
int settingReplicas = 0;
// 判斷索引是否存在,存在則刪除
IndicesExistsResponse indicesExistsResponse = client.admin().indices().prepareExists(bookIndex).get();
if (indicesExistsResponse.isExists()) {
System.out.println("索引 " + bookIndex + " 存在!");
// 刪除索引,防止報異常 ResourceAlreadyExistsException[index [bookdb_index/yL05ZfXFQ4GjgOEM5x8tFQ] already exists
DeleteIndexResponse deleteResponse = client.admin().indices().prepareDelete(bookIndex).get();
if (deleteResponse.isAcknowledged()){
System.out.println("索引" + bookIndex + "已刪除");
}else {
System.out.println("索引" + bookIndex + "刪除失敗");
}
} else {
System.out.println("索引 " + bookIndex + " 不存在!");
}
// 設定Settings
CreateIndexResponse response = client.admin().indices().prepareCreate(bookIndex)
.setSettings(Settings.builder()
.put("index.number_of_shards", settingShards)
.put("index.number_of_replicas", settingReplicas))
.get();
// 檢視結果
GetSettingsResponse getSettingsResponse = client.admin().indices()
.prepareGetSettings(bookIndex).get();
System.out.println("索引設定結果");
for (ObjectObjectCursor<String, Settings> cursor : getSettingsResponse.getIndexToSettings()) {
String index = cursor.key;
Settings settings = cursor.value;
Integer shards = settings.getAsInt("index.number_of_shards", null);
Integer replicas = settings.getAsInt("index.number_of_replicas", null);
System.out.println("index:" + index + ", shards:" + shards + ", replicas:" + replicas);
Assert.assertEquals(java.util.Optional.of(settingShards), java.util.Optional.of(shards));
Assert.assertEquals(java.util.Optional.of(settingReplicas), java.util.Optional.of(replicas));
}
}
/**
* Bulk 批量插入資料
*/
@Test
public void bulk() {
List<Book> list = DateUtil.batchData();
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
// 新增index操作到 bulk 中
list.forEach(book -> {
// 新版的API中使用setSource時,引數的個數必須是偶數,否則需要加上 setSource(json, XContentType.JSON)
bulkRequestBuilder.add(client.prepareIndex(bookIndex, bookType, book.getId()).setSource(gson.toJson(book), XContentType.JSON));
});
BulkResponse responses = bulkRequestBuilder.get();
if (responses.hasFailures()) {
// bulk有失敗
for (BulkItemResponse res : responses) {
System.out.println(res.getFailure());
}
Assert.assertTrue(false);
}
}
}
複製程式碼
開始查詢
控制類
查詢介面
@RestController
@RequestMapping("basicmatch")
public class BasicMatchQueryController {
@Autowired
private BasicMatchQueryService basicMatchQueryService;
/**
* 1.1 對 "guide" 執行全文檢索
* 測試:http://localhost:8080/basicmatch/multimatch?query=guide
*/
@RequestMapping("multimatch")
public Response<List<Book>> multiMatch(@RequestParam(value = "query", required = true) String query) {
return basicMatchQueryService.multiBatch(query);
}
/**
* 1.2 指定特定欄位檢索
* 測試:http://localhost:8080/basicmatch/match?title=in action&from=0&size=4
*/
@RequestMapping("match")
public ResponsePage<List<Book>> match(MatchForm form) {
return basicMatchQueryService.match(form);
}
/**
* 2 對 "guide" 執行多欄位檢索
* 測試:http://localhost:8080/basicmatch/multifield?query=guide
*/
@RequestMapping("multifield")
public Response<List<Book>> multiField(@RequestParam(value = "query", required = true) String query) {
return basicMatchQueryService.multiField(query);
}
/**
* 3、 Boosting提升某欄位得分的檢索( Boosting): 將“摘要”欄位的得分提高了3倍
* 測試:http://localhost:8080/basicmatch/multifieldboost?query=elasticsearch guide
*/
@RequestMapping("multifieldboost")
public Response<List<Book>> multiFieldboost(@RequestParam(value = "query", required = true) String query) {
return basicMatchQueryService.multiFieldboost(query);
}
/**
* 4、Bool檢索( Bool Query)
* 測試:http://localhost:8080/basicmatch/bool?shouldTitles=Elasticsearch&shouldTitles=Solr&mustAuthors=clinton gormely&mustNotAuthors=radu gheorge
*/
@RequestMapping("bool")
public Response<List<Book>> bool(@ModelAttribute BoolForm form) {
return basicMatchQueryService.bool(form);
}
/**
* 5、 Fuzzy 模糊檢索( Fuzzy Queries)
*/
@RequestMapping("fuzzy")
public Response<List<Book>> fuzzy(String query) {
return basicMatchQueryService.fuzzy(query);
}
/**
* 6、 Wildcard Query 萬用字元檢索
* 測試:http://localhost:8080/basicmatch/wildcard?pattern=t*
*/
@RequestMapping("wildcard")
public Response<List<Book>> wildcard(String pattern) {
return basicMatchQueryService.wildcard(Constants.AUTHORS, pattern);
}
/**
* 7、正規表示式檢索( Regexp Query)
* 測試:http://localhost:8080/basicmatch/regexp
*/
@RequestMapping("regexp")
public Response<List<Book>> regexp(String regexp) {
// 由於Tomcat的原因,直接接收有特殊字元的 正規表示式 會異常,所以這裡寫死,不過多探究
// 若
regexp = "t[a-z]*y";
return basicMatchQueryService.regexp(Constants.AUTHORS, regexp);
}
/**
* 8、匹配短語檢索( Match Phrase Query)
* 測試:http://localhost:8080/basicmatch/phrase?query=search engine
*/
@RequestMapping("phrase")
public Response<List<Book>> phrase(String query) {
return basicMatchQueryService.phrase(query);
}
/**
* 9、匹配片語字首檢索
* 測試:http://localhost:8080/basicmatch/phraseprefix?query=search en
*/
@RequestMapping("phraseprefix")
public Response<List<Book>> phrasePrefix(String query) {
return basicMatchQueryService.phrasePrefix(query);
}
/**
* 10、字串檢索( Query String)
* 測試:http://localhost:8080/basicmatch/querystring?query=(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)
*/
@RequestMapping("querystring")
public Response<List<Book>> queryString(String query) {
return basicMatchQueryService.queryString(query);
}
/**
* 11、簡化的字串檢索 (Simple Query String)
* 測試:http://localhost:8080/basicmatch/simplequerystring?query=(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)
*/
@RequestMapping("simplequerystring")
public Response<List<Book>> simplequerystring(String query) {
// 這裡寫死,僅為測試
query = "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)";
return basicMatchQueryService.simpleQueryString(query);
}
/**
* 12、Term=檢索(指定欄位檢索)
* 測試:http://localhost:8080/basicmatch/term?query=manning
*/
@RequestMapping("term")
public Response<List<Book>> term(String query) {
return basicMatchQueryService.term(query);
}
/**
* 13、Term排序檢索-(Term Query - Sorted)
* 測試:http://localhost:8080/basicmatch/termsort?query=manning
*/
@RequestMapping("termsort")
public Response<List<Book>> termsort(String query) {
return basicMatchQueryService.termsort(query);
}
/**
* 14、範圍檢索(Range query)
* 測試:http://localhost:8080/basicmatch/range?startDate=2015-01-01&endDate=2015-12-31
*/
@RequestMapping("range")
public Response<List<Book>> range(String startDate, String endDate) {
return basicMatchQueryService.range(startDate, endDate);
}
/**
* 15. 過濾檢索
* 測試:http://localhost:8080/basicmatch/filter?query=elasticsearch>e=20
*/
@RequestMapping("filter")
public Response<List<Book>> filter(String query, Integer gte, Integer lte) {
return basicMatchQueryService.filter(query, gte, lte);
}
/**
* 17、 Function 得分:Field值因子( Function Score: Field Value Factor)
* 測試:http://localhost:8080/basicmatch/fieldvaluefactor?query=search engine
*/
@RequestMapping("fieldvaluefactor")
public Response<List<Book>> fieldValueFactor(String query) {
return basicMatchQueryService.fieldValueFactor(query);
}
/**
* 18、 Function 得分:衰減函式( Function Score: Decay Functions )
* 測試:http://localhost:8080/basicmatch/decay?query=search engines&origin=2014-06-15
*/
@RequestMapping("decay")
public Response<List<Book>> decay(String query, @RequestParam(value = "origin", defaultValue = "2014-06-15") String origin) {
return basicMatchQueryService.decay(query, origin);
}
/**
* 19、Function得分:指令碼得分( Function Score: Script Scoring )
* 測試:ES需要配置允許groovy指令碼執行才可以
*/
@RequestMapping("script")
public Response<List<Book>> script(String query, @RequestParam(value = "threshold", defaultValue = "2015-07-30") String threshold) {
return basicMatchQueryService.script(query, threshold);
}
}
複製程式碼
服務類
@Service
public class BasicMatchQueryService {
@Autowired
private Client client;
@Value("${elasticsearch.bookIndex}")
private String bookIndex;
@Value("${elasticsearch.bookType}")
private String bookType;
/**
* 進行ES查詢,執行請求前後列印出 查詢語句 和 查詢結果
*/
private SearchResponse requestGet(String queryName, SearchRequestBuilder requestBuilder) {
System.out.println(queryName + " 構建的查詢:" + requestBuilder.toString());
SearchResponse searchResponse = requestBuilder.get();
System.out.println(queryName + " 搜尋結果:" + searchResponse.toString());
return searchResponse;
}
...
}
複製程式碼
1.1 對 “guide” 執行全文檢索 Multi Match Query
public Response<List<Book>> multiBatch(String query) {
MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(query);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(queryBuilder);
SearchResponse searchResponse = requestGet("multiBatch", requestBuilder);
return CommonQueryUtils.buildResponse(searchResponse);
}
複製程式碼
1.2 在標題欄位(title)中搜尋帶有 “in action” 字樣的圖書
public ResponsePage<List<Book>> match(MatchForm form) {
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("title", form.getTitle());
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").fragmentSize(200);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(matchQueryBuilder)
.setFrom(form.getFrom()).setSize(form.getSize())
.highlighter(highlightBuilder)
// 設定 _source 要返回的欄位
.setFetchSource(Constants.fetchFieldsTSPD, null);
...
}
複製程式碼
多欄位檢索 (Multi-field Search)
public Response<List<Book>> multiField(String query) {
MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(query).field("title").field("summary");
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(queryBuilder);
...
}
複製程式碼
3、 Boosting提升某欄位得分的檢索( Boosting),將“摘要”欄位的得分提高了3倍
public Response<List<Book>> multiFieldboost(String query) {
MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(query).field("title").field("summary", 3);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(queryBuilder);
...
}
複製程式碼
4、Bool檢索( Bool Query)
/**
* 在標題中搜尋一本名為 "Elasticsearch" 或 "Solr" 的書,
* AND由 "clinton gormley" 創作,但NOT由 "radu gheorge" 創作
*/
public Response<List<Book>> bool(BoolForm form) {
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
// 搜尋標題 should
BoolQueryBuilder shouldTitleBool = new BoolQueryBuilder();
form.getShouldTitles().forEach(title -> {
shouldTitleBool.should().add(new MatchQueryBuilder("title", title));
});
boolQuery.must().add(shouldTitleBool);
// match 作者
form.getMustAuthors().forEach(author -> {
boolQuery.must().add(new MatchQueryBuilder("authors", author));
});
// not match 作者
form.getMustNotAuthors().forEach(author -> {
boolQuery.mustNot().add(new MatchQueryBuilder("authors", author));
});
...
}
複製程式碼
5、 Fuzzy 模糊檢索( Fuzzy Queries)
public Response<List<Book>> fuzzy(String query) {
MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(query)
.field("title").field("summary")
.fuzziness(Fuzziness.AUTO);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(queryBuilder)
.setFetchSource(Constants.fetchFieldsTSPD, null)
.setSize(2);
...
}
複製程式碼
6、 Wildcard Query 萬用字元檢索
/**
* 要查詢具有以 "t" 字母開頭的作者的所有記錄
*/
public Response<List<Book>> wildcard(String fieldName, String pattern) {
WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(fieldName, pattern);
HighlightBuilder highlightBuilder = new HighlightBuilder().field(Constants.AUTHORS, 200);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setTypes(bookType).setQuery(wildcardQueryBuilder)
.setFetchSource(Constants.fetchFieldsTA, null)
.highlighter(highlightBuilder);
}
複製程式碼
7、正規表示式檢索( Regexp Query)
public Response<List<Book>> regexp(String fieldName, String regexp) {
RegexpQueryBuilder queryBuilder = new RegexpQueryBuilder(fieldName, regexp);
HighlightBuilder highlightBuilder = new HighlightBuilder().field(Constants.AUTHORS);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex)
.setQuery(queryBuilder).setTypes(bookType).highlighter(highlightBuilder)
.setFetchSource(Constants.fetchFieldsTA, null);
}
複製程式碼
8、匹配短語檢索( Match Phrase Query)
public Response<List<Book>> phrase(String query) {
MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder(query)
.field(Constants.TITLE).field(Constants.SUMMARY)
.type(MultiMatchQueryBuilder.Type.PHRASE).slop(3);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder)
.setFetchSource(Constants.fetchFieldsTSPD, null);
}
複製程式碼
9、匹配片語字首檢索
public Response<List<Book>> phrasePrefix(String query) {
MatchPhrasePrefixQueryBuilder queryBuilder = new MatchPhrasePrefixQueryBuilder(Constants.SUMMARY, query)
.slop(3).maxExpansions(10);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSPD, null);
}
複製程式碼
10、字串檢索( Query String)
public Response<List<Book>> queryString(String query) {
QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(query);
queryBuilder.field(Constants.SUMMARY, 2).field(Constants.TITLE)
.field(Constants.AUTHORS).field(Constants.PUBLISHER);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSA, null);
}
複製程式碼
11、簡化的字串檢索 (Simple Query String)
public Response<List<Book>> simpleQueryString(String query) {
SimpleQueryStringBuilder queryBuilder = new SimpleQueryStringBuilder(query);
queryBuilder.field(Constants.SUMMARY, 2).field(Constants.TITLE)
.field(Constants.AUTHORS).field(Constants.PUBLISHER);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSA, null)
.highlighter(Constants.highlightS);
}
複製程式碼
12、Term/Terms檢索(指定欄位檢索)
public Response<List<Book>> term(String query) {
TermQueryBuilder termQueryBuilder = new TermQueryBuilder(Constants.PUBLISHER, query);
// terms 查詢
/*String[] values = {"manning", "oreilly"};
TermsQueryBuilder termsQueryBuilder = new TermsQueryBuilder(Constants.PUBLISHER, values);*/
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(termQueryBuilder)
.setFetchSource(Constants.fetchFieldsTPPD, null);
}
複製程式碼
13、Term排序檢索-(Term Query – Sorted)
public Response<List<Book>> termsort(String query) {
TermQueryBuilder termQueryBuilder = new TermQueryBuilder(Constants.PUBLISHER, query);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(termQueryBuilder)
.addSort(Constants.PUBLISHER_KEYWORD, SortOrder.DESC)
.addSort(Constants.TITLE_KEYWORD, SortOrder.ASC)
.setFetchSource(Constants.fetchFieldsTPPD, null);
}
複製程式碼
14、範圍檢索(Range query)
public Response<List<Book>> range(String startDate, String endDate) {
RangeQueryBuilder queryBuilder = new RangeQueryBuilder(Constants.PUBLISHDATE)
.gte(startDate).lte(endDate);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder)
.setFetchSource(Constants.fetchFieldsTPPD, null);
}
複製程式碼
15. 過濾檢索
public Response<List<Book>> filter(String query, Integer gte, Integer lte) {
BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
queryBuilder.must().add(new MultiMatchQueryBuilder(query).field(Constants.TITLE).field(Constants.SUMMARY));
if (gte != null || lte != null) {
RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder(Constants.NUM_REVIEWS);
if (gte != null) {
rangeQueryBuilder.gte(gte);
}
if (lte != null) {
rangeQueryBuilder.lte(lte);
}
queryBuilder.filter().add(rangeQueryBuilder);
}
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSPN, null);
}
複製程式碼
17、 Function 得分:Field值因子( Function Score: Field Value Factor)
public Response<List<Book>> fieldValueFactor(String query) {
// query
MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(query)
.field(Constants.TITLE).field(Constants.SUMMARY);
// fieldValueFactor
FieldValueFactorFunctionBuilder fieldValueFactor = ScoreFunctionBuilders.fieldValueFactorFunction(Constants.NUM_REVIEWS)
.factor(2).modifier(FieldValueFactorFunction.Modifier.LOG1P);
// functionscore
FunctionScoreQueryBuilder queryBuilder = QueryBuilders.functionScoreQuery(multiMatchQueryBuilder, fieldValueFactor);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSPN, null);
}
複製程式碼
18、 Function 得分:衰減函式( Function Score: Decay Functions )
public Response<List<Book>> decay(String query, String origin) {
MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(query)
.field(Constants.TITLE).field(Constants.SUMMARY);
ExponentialDecayFunctionBuilder exp = ScoreFunctionBuilders.exponentialDecayFunction(Constants.PUBLISHDATE, origin, "30d", "7d");
FunctionScoreQueryBuilder queryBuilder = QueryBuilders.functionScoreQuery(multiMatchQueryBuilder, exp).boostMode(CombineFunction.REPLACE);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSPN, null);
}
複製程式碼
19、Function得分:指令碼得分( Function Score: Script Scoring )
public Response<List<Book>> script(String query, String threshold) {
MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder(query)
.field(Constants.TITLE).field(Constants.SUMMARY);
// 引數
Map<String, Object> params = new HashMap<>();
params.put("threshold", threshold);
// 指令碼
String scriptStr = "publish_date = doc[`publish_date`].value; num_reviews = doc[`num_reviews`].value; if (publish_date > Date.parse(`yyyy-MM-dd`, threshold).getTime()) { return log(2.5 + num_reviews) }; return log(1 + num_reviews);";
Script script = new Script(ScriptType.INLINE, "painless", scriptStr, params);
ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(script);
FunctionScoreQueryBuilder queryBuilder = QueryBuilders.functionScoreQuery(multiMatchQueryBuilder, scriptScoreFunctionBuilder);
SearchRequestBuilder requestBuilder = client.prepareSearch(bookIndex).setTypes(bookType)
.setQuery(queryBuilder).setFetchSource(Constants.fetchFieldsTSPN, null);
}
複製程式碼
更多內容請訪問我的個人部落格:laijianfeng.org/
開啟微信掃一掃,關注【小旋鋒】微信公眾號,及時接收博文推送