elasticsearch customScoreQuery 实例

我们来学习一下elasticsearch customScoreQuery 的使用。customScoreQuery 可以自定义score,从而来影响排序结果。

建立mapping


public static XContentBuilder createMapping(String indexName){
XContentBuilder mapping = null;
try {
mapping = jsonBuilder()
.startObject()
// 索引库名(类似数据库中的表)
.startObject(indexName)
 
.startObject("properties")
// 新闻ID
.startObject("id")
.field("type", "long")
.field("store", "yes")
.field("index", "not_analyzed")
.field("include_in_all", "false")
.endObject()
 
// title
.startObject("titele")
.field("type", "string")
.field("store", "yes")
.field("term_vector","with_positions_offsets")
.field("indexAnalyzer", "ik")
.field("searchAnalyzer", "ik")
.field("include_in_all", "false")
.field("boost", 4.0) // 打分(默认1.0)
.endObject()
                                .startObject("updatetime")
.field("type", "string")
.field("store", "yes")
.field("include_in_all", "false")
.endObject()
.endObject()
.endObject()
.endObject();
} catch (IOException e) {
e.printStackTrace();
}
 
return mapping;
}


创建索引


public static void createIndex(String indexName, String indexType){
 
 
   Client esClient = ESServiceSingleton2.getTransportClient();
 
   // 创建Mapping
   XContentBuilder mapping = createMapping(indexName);
// 创建一个空索引
 
   esClient.admin().indices().prepareCreate(indexName).execute().actionGet();
 
PutMappingRequest mappingRequest = Requests.putMappingRequest(indexName).type(indexType).source(mapping);
esClient.admin().indices().putMapping(mappingRequest).actionGet();
 
 
}


添加索引数据:

public static Integer addIndex(String indexName, String indexType){
 
 
   Client esClient = ESServiceSingleton2.getTransportClient();
 
 
BulkRequestBuilder bulkRequest = esClient.prepareBulk();   
 
 
try{
bulkRequest.add(esClient.prepareIndex(indexName, indexType, ""+5)   
  .setSource(jsonBuilder()
.startObject()
.field("id", 1)
 
.field("title", "脱北者中国")
.field("updatetime","1370563200")
.endObject())
       );
bulkRequest.add(esClient.prepareIndex(indexName, indexType, ""+2)   
  .setSource(jsonBuilder()
.startObject()
.field("id", 2)
 
.field("title", "脱北者中国")
.field("updatetime","1350327958")
.endObject())
       );
}catch(Exception e){
e.printStackTrace();
}
bulkRequest.execute().actionGet();   
 
 
return bulkRequest.numberOfActions();
}

创建查询:

public static void query(String query,String indexName,String indexType){
Client client = ESServiceSingleton2.getTransportClient();
 
SearchResponse response = client.prepareSearch(indexName)
       .setTypes(indexType)
       //.setQuery(getQueryBuilder(query))
       .setQuery(new CustomScoreQueryBuilder(getQueryBuilder(query)).script(
"long x=Long.parseLong(doc['updatetime'].value);" +
       "x=x/86400l;"+
"_score=_score+sqrt(yy-x)"
).param("yy", System.currentTimeMillis()/1000l/86400l))
 
       .addFields("id","title","updatetime")
       .setFrom(0).setSize(60).setExplain(true)
       .addHighlightedField("title")
                .setHighlighterEncoder("UTF-8")
                .setHighlighterPreTags("<em>")
                .setHighlighterPostTags("</em>")
       .execute()
       .actionGet();
 
 
Float usetime = response.getTookInMillis()/1000f;
     // 命中记录数
     Long hits = response.getHits().totalHits();
     System.out.println("usetime:"+usetime+"  hits:"+hits);
     for (SearchHit hit : response.getHits()) {
     Float score = hit.getScore();
         // 文章id
         Integer id = Integer.parseInt(hit.getFields().get("id").value().toString());
         String title = hit.getHighlightFields().containsKey("title")?hit.getHighlightFields().get("title").getFragments()[0].toString():hit.getFields().get("title").value().toString();
         Long updatetime = Long.parseLong(hit.getFields().get("updatetime").value().toString());
         System.out.println("the record id:"+id+" title: "+title+" updatetime:"+updatetime+"  score:"+score);
     }
}

获取querybuilder
public static QueryBuilder getQueryBuilder(String query){
		QueryStringQueryBuilder qsqb=new QueryStringQueryBuilder(query);
		qsqb.analyzer("ik").field("title");
	        return qsqb;
	}

主函数
public class IndexTest {
	public static void main(String[] args){
		Client client = ESServiceSingleton2.getTransportClient();
		client.admin().indices().prepareDelete("test").execute().actionGet();
		createIndex("test", "xq");
		addIndex("test", "xq");
		client.admin().indices().prepareRefresh().execute().actionGet();
		query("北","test", "xq");
		client.close();
	}
}
当时操作出现了空指针错误。

[2013-06-08 16:44:00,730][DEBUG][action.search.type       ] [Golem] [test][1], node[h9UqCv4wTECtb_VLWnkxcQ], [P], s[STARTED]: Failed to execute [org.elasticsearch.action.search.SearchRequest@175edcf]
org.elasticsearch.search.query.QueryPhaseExecutionException: [test][1]: query[filtered(custom score (title:北,function=script[long x=Long.parseLong(doc['updatetime'].value);x=x/86400l;long nows=yy/86400l;int nowDay=(int)nows;int day=(int)x;if (day < nowDay) {} else if (day > nowDay) {} else{}], params [{_source=org.elasticsearch.search.lookup.SourceLookup@1cfefc3, nows=15864, _fields=org.elasticsearch.search.lookup.FieldsLookup@86100a, _doc=org.elasticsearch.search.lookup.DocLookup@1871341, doc=org.elasticsearch.search.lookup.DocLookup@1871341, day=15910, _score=0.13424811, nowDay=15864, yy=1370681040, x=15910.719386574074}]))->cache(_type:xq)],from[0],size[60]: Query Failed [Failed to execute main query]
	at org.elasticsearch.search.query.QueryPhase.execute(QueryPhase.java:138)
	at org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:239)
	at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteQuery(SearchServiceTransportAction.java:141)
	at org.elasticsearch.action.search.type.TransportSearchQueryThenFetchAction$AsyncAction.sendExecuteFirstPhase(TransportSearchQueryThenFetchAction.java:80)
	at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:206)
	at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:193)
	at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$2.run(TransportSearchTypeAction.java:179)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NullPointerException
	at org.elasticsearch.script.mvel.MvelScriptEngineService$MvelSearchScript.runAsFloat(MvelScriptEngineService.java:197)
	at org.elasticsearch.index.query.CustomScoreQueryParser$ScriptScoreFunction.score(CustomScoreQueryParser.java:135)
	at org.elasticsearch.common.lucene.search.function.FunctionScoreQuery$CustomBoostFactorScorer.score(FunctionScoreQuery.java:155)
	at org.apache.lucene.search.TopScoreDocCollector$OutOfOrderTopScoreDocCollector.collect(TopScoreDocCollector.java:140)
	at org.apache.lucene.search.Scorer.score(Scorer.java:65)
	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:612)
	at org.elasticsearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:161)
	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:482)
	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:438)
	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:281)
	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:269)
	at org.elasticsearch.search.query.QueryPhase.execute(QueryPhase.java:134)
	... 9 more

代码为:
new CustomScoreQueryBuilder(getQueryBuilder(query)).script(
 "long x=Long.parseLong(doc['updatetime'].value);" +
         "x=x/86400l;" 
 ).param("yy", System.currentTimeMillis()/1000l/86400l)

从上面代码看,script没有问题,最后查到原因,CustomScoreQueryBuilder 必须要对_score 赋值,不然回报空指针错误。

customScoreQuery 的script 采用的是mvel的语法。mvel采用了类似java的语法。更多详细资料可参考:
http://blog.csdn.net/fhm727/article/details/6543152

获取java client可参考:http://www.chepoo.com/elasticsearch-java-client-demo.html

customScoreQuery 的script的函数支持可参考:
http://www.elasticsearch.org/guide/reference/modules/scripting/

customScoreQuery 的语法可参考:
http://www.elasticsearch.org/guide/reference/query-dsl/custom-score-query/
http://www.elasticsearch.org/guide/reference/query-dsl/custom-boost-factor-query/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值