java multiMatchQuery 怎么提高某个字段的权重?

Elasticsearch | 作者 zev | 发布于2018年07月18日 | 阅读数:8408

2018-07-18_115952.png

 
如上图,提高 ' 项目名称 ' 这个字段的权重, 有javaAPI可以实现吗?
已邀请:

kennywu76 - Wood

赞同来自: zev denghc0607

@zev
 
看了下multiMatchQuery的源码,的确会给所有的fields加一个默认的boost  1.0,造成字段上给的权重值被当作了field的一部分。
 /**
* Constructs a new text query.
*/
public MultiMatchQueryBuilder(Object value, String... fields) {
if (value == null) {
throw new IllegalArgumentException("[" + NAME + "] requires query value");
}
if (fields == null) {
throw new IllegalArgumentException("[" + NAME + "] requires fields at initialization time");
}
this.value = value;
this.fieldsBoosts = new TreeMap<>();
### 调用field()方法添加字段
for (String field : fields) {
field(field);
}
}



...........


/**
* Adds a field to run the multi match against.
*/
public MultiMatchQueryBuilder field(String field) {
if (Strings.isEmpty(field)) {
throw new IllegalArgumentException("supplied field is null or empty.");
}
#### 添加的字段都设置了一个默认的DEFAULT_BOOST
this.fieldsBoosts.put(field, AbstractQueryBuilder.DEFAULT_BOOST);
return this;
}


不过有一个fileds()方法,可以添加自定义boost的字段
    /**
* Add several fields to run the query against with a specific boost.
*/
public MultiMatchQueryBuilder fields(Map<String, Float> fields) {
this.fieldsBoosts.putAll(fields);
return this;
}

其中fileds是一个字段名称为key, boost数值为value的Map。 
 
因此,你可以这么来构造Query:
QueryBuilders.multiMatchQuery(keyword).fields(weightMap)

也就是调用已fields方法,并传入自定义权重的map作为参数。
 
 
PS.  官方的client SDK文档不够详细,没有对此做说明。
 

kennywu76 - Wood

赞同来自: zev

JAVA api参照   来写就行了,其中fields的名称上可以通过^符号带上权重,格式和json dsl里一样,如 "项目名称^5" 。

God_lockin

赞同来自: sodyu

这个是构建带权重的query用的
private QueryBuilder setCustomScoreQueryCmd(CustomScoreSearchRequest request) {

QueryBuilder qb = QueryBuilders.matchAllQuery();
List<QueryItem> queryItems = request.getQueryItems();
if (!(null == queryItems || queryItems.isEmpty())) {
qb = new MultiMatchQueryBuilder(request.getQueryText());
if (StringUtils.isNotBlank(request.getMultiQueryType())) {
((MultiMatchQueryBuilder) qb).type(request.getMultiQueryType());
}

if (StringUtils.isNotBlank(request.getMultiQueryOperator())) {
if (MultiQueryOperator.AND.equals(request.getMultiQueryOperator().toUpperCase())) {
((MultiMatchQueryBuilder) qb).operator(Operator.AND);
} else if (MultiQueryOperator.OR.equals(request.getMultiQueryOperator().toUpperCase())) {
((MultiMatchQueryBuilder) qb).operator(Operator.OR);
}
} else {
((MultiMatchQueryBuilder) qb).operator(Operator.AND);
}

// set query
for (int i = 0; i < queryItems.size(); i ++) {
QueryItem tqi = queryItems.get(i);
((MultiMatchQueryBuilder) qb).field(tqi.getField(), tqi.getBoost());
}
}

BoolQueryBuilder bqb = SearchUtils.setCommonQueryCmd(request);
bqb.must(qb);

return bqb;
}
在Query里面主要就加几个属性
"queryItems":[ // 设定目标字段及权重值
{
"field":"title",  // 字段名
"boost":15 // 权重值,float 型
}
"queryText":"住院",  // 如果填,则是各字段中需要被检索的内容
"multiQueryOperator":"and", // 可选,默认 and, 补全检索逻辑条件
"multiQueryType":"most_fields", // 可选,best_fields / most_fields / cross_fields / phrase / phrase_prefix
 
组合出来的query,再在SearchRequestBuilder里面builder.setQuery(qb);
就可以执行
SearchResponse esResponse = builder.execute().actionGet();
来取结果了

zev

赞同来自:



1.png

 
2.png

 

要回复问题请先登录注册