关于ES查询文档标记来源问题
1.目前知了使用的方案
知了目前使用的是ES为Java提供一个查询接口,叫做QueryBuilder
当用户传入查询后,现在我们做了一个这个事情——多字段匹配查询
reBuilder = reBuilder.must(multiMatchQuery(query, "title", "text"));
其中这个query就是用户的输入
官方文档给出的解释是:Finds documents which match any field, but uses the _score from the best field.
实际上这个多字段匹配查询可以这么理解:
比如说用户搜索一个「北京邮电大学」
我在标题和正文里分别对北京邮电大学进行全文检索,然后分别在两个字段里按照命中率(或者说_score)进行排序
然后将这两个排序结果取并集,在两个字段命中率都高的排名考前
最后得到一个没有重复的文档集合,返回给用户
这就造成一个问题,通过这种方法获得的结果是这样的
["0": {
"id": 17516,
"crop_id": null,
"user_id": 23,
"create_time": 1631950049000,
"edit_time": 1631950049000,
"title": "计算机学院2021级培养方案",
"text": "<p>计算机学院2021级培养方案,包括:</p><p>北京邮电大学专业学位硕士研究生培养方案(2021级)-9.14.pdf<br />北京邮电大学博士研究 生培养方案(2021级)-9.3.pdf<br />北京邮电大学学术学位硕士研究生培养方案(2021级)-9.9.pdf<br />北京邮电大学直博研究生培养方案(2021级)-9.3.pdf</p>",
"attachment": null,
"superior": 0,
"recognition": null,
"opposition": null,
"pageview": null,
"collection": null,
"group_id": "",
"label_id": "111,203,129",
"user_name": null,
"group_name": null,
"label_name": null,
"permissionid": "0"
}]
是一个一个数组的形式,没有命中率,也不知道是在标题还是正文还是附件搜出来的
2.或许可以采用的解决方法
自行封装一个查询函数,来实现一个类似于多字段查询的功能
主要原理还是调用ES的最原生的Restful API分别查询各个字段,再按照我们的规则进行合并,例如
POST http://192.168.36.136:9200/_search
{
"query": {
"query_string": {
"query": "北京邮电大学"
}
}
}
可以得到这样的返回
{
"took": 246,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 105,
"max_score": 15.921347,
"hits": [
{
"_index": "knowledge_ms",
"_type": "resource",
"_id": "17516",
"_score": 15.921347, # 这里能得到一个命中率
"_source": {
"id": 17516,
"crop_id": null,
"user_id": 23,
"create_time": 1631950049000,
"edit_time": 1631950049000,
"title": "计算机学院2021级培养方案",
"text": "<p>计算机学院2021级培养方案,包括:</p><p>北京邮电大学专业学位硕士研究生培养方案(2021级)-9.14.pdf<br />北 京邮电大学博士研究生培养方案(2021级)-9.3.pdf<br />北京邮电大学学术学位硕士研究生培养方案(2021级)-9.9.pdf<br />北京邮电大学直博研究生培养方案(2021级)-9.3.pdf</p>",
"attachment": null,
按照这样的规则我们能分别得到标题命中率的排名、正文命中率的排名和附件命中率的排名
然后我们可以对这三个排名拉一个(可能有重复文档的)大排名给用户展示出来,并且告诉用户是哪里搜出来的
最后得到的感觉大概是这个样子