Node.js 基于ElasticSearch的搜索与排序
我把ES作为我的SE来实现,我有一些关于我做错了什么的问题 主要的想法是有一组帖子,我想在一些文本字段上搜索,然后根据相关性和其中一个字段的创建日期对结果进行排序。我正在使用带有默认es库的node js 以下是我的映射:Node.js 基于ElasticSearch的搜索与排序,node.js,search,elasticsearch,Node.js,Search,elasticsearch,我把ES作为我的SE来实现,我有一些关于我做错了什么的问题 主要的想法是有一组帖子,我想在一些文本字段上搜索,然后根据相关性和其中一个字段的创建日期对结果进行排序。我正在使用带有默认es库的node js 以下是我的映射: { "version": 1, "conf": { "settings": { "analysis": { "filter": { "snowball": { "type": "snowb
{
"version": 1,
"conf": {
"settings": {
"analysis": {
"filter": {
"snowball": {
"type": "snowball",
"language": "English"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"english_possessive_stemmer": {
"type": "stemmer",
"language": "possessive_english"
},
"stopwords": {
"type": "stop",
"stopwords": ["_english_"]
},
"worddelimiter": {
"type": "word_delimiter"
}
},
"tokenizer": {
"nGram": {
"type": "nGram",
"min_gram": 3,
"max_gram": 20
}
},
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "nGram",
"filter": [
"stopwords",
"asciifolding",
"lowercase",
"snowball",
"english_stemmer",
"english_possessive_stemmer",
"worddelimiter"
]
},
"custom_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"stopwords",
"asciifolding",
"lowercase",
"snowball",
"english_stemmer",
"english_possessive_stemmer",
"worddelimiter"
]
}
}
}
},
"mappings": {
"posts": {
"model": "Post",
"properties": {
"id": {
"type": "long"
},
"title": {
"type": "string",
"analyzer": "custom_analyzer",
"boost": 5
},
"description": {
"type": "string",
"analyzer": "custom_analyzer",
"boost": 4
},
"categories": {
"type": "string",
"analyzer": "custom_analyzer"
},
"seller": {
"type": "object",
"properties": {
"id": {
"type": "long"
},
"username": {
"type": "string",
"analyzer": "custom_analyzer",
"boost": 1
},
"firstName": {
"type": "string",
"analyzer": "custom_analyzer",
"boost": 3
},
"lastName": {
"type": "string",
"analyzer": "custom_analyzer",
"boost": 2
}
}
},
"marketPrice": {
"type": "float"
},
"currentPrice": {
"type": "float"
},
"discount": {
"type": "float"
},
"commentsCount": {
"type": "integer",
"index": "not_analyzed"
},
"likesCount": {
"type": "integer",
"index": "not_analyzed"
},
"created": {
"type": "date",
"index": "not_analyzed"
},
"modified": {
"type": "date",
"index": "not_analyzed"
}
}
}
}
}
}
我为10份文件编制了索引:
| id | title | description | market_price | item_condition | iso | comment_count | created |
| 1 | Post 1 | Post 1 Description | 1 | 1 | 1 | 1 | 2014/01/01 |
| 2 | Post 2 | Post 2 Description | 1 | 1 | 1 | 1 | 2014/01/02 |
| 3 | Post 3 | Post 3 Description | 1 | 1 | 1 | 1 | 2014/01/03 |
| 4 | Post 4 | Post 4 Description | 1 | 1 | 1 | 1 | 2014/01/04 |
| 5 | Post 5 | Post 5 Description | 1 | 1 | 1 | 1 | 2014/01/05 |
| 6 | Post 6 | Post 6 Description | 1 | 1 | 1 | 1 | 2014/01/06 |
| 7 | Post 7 | Post 7 Description | 1 | 1 | 1 | 1 | 2014/01/07 |
| 8 | Post 8 | Post 8 Description | 1 | 1 | 1 | 1 | 2014/01/08 |
| 9 | Post 9 | Post 9 Description | 1 | 1 | 1 | 1 | 2014/01/09 |
| 10 | Post 10 | Post 10 Description | 1 | 1 | 1 | 1 | 2014/01/010 |
假设卖家信息有两个,我不在这里添加它,因为帖子会很广泛
我的问题是:
GET /clamour_develop/_search
{
"query": {
"multi_match": {
"query": "post 1",
"fields": [ "title", "description", "seller.first_name", "seller.last_name", "seller.username" ],
"analyzer": "custom_search_analyzer"
}
},
"sort": [
{
"_score":{
"order": "desc"
}
},{
"created": {
"order": "desc"
}
}
]
}
我希望收到订单中的文件
Post 1
Post 10
Post 9
Post 8
Post 7
Post 6
Post 5
Post 4
Post 3
Post 2
但我明白了
Post 1
Post 10
Post 8
Post 3
Post 9
Post 7
Post 6
Post 4
Post 2
Post 5
编辑:
我做错了什么?您必须在搜索查询中添加以下内容:
"track_scores": true
在字段上排序时,不会计算分数。通过将track_scores设置为true,仍将计算和跟踪分数
有关搜索API中排序参数的更多详细信息,您可以查看官方文档我发现计算分数取决于每个文档所在的分片以及每个分片中的文档数量。在你的案例中,我在对你的要点的解释中看到:
shard 0, documents(id):9,4,
shard 1, documents(id):5
shard 2, documents(id):1,6
shard 3, documents(id):2,7
shard 4, documents(id):3,8,10
您正在搜索后学期和1学期。很明显,id为1的文档在匹配术语和结果时得分最高。
您可以看到,id为5的文档是shard 5中唯一的文档,也是得分最低的文档。下面是ES中最重要的相关性计算:反向文档频率。当你看这个公式时:
idft=1+记录numDocs/docFreq+1,并将numDocsmaxDocs值和docFreq值从id 5:1+记录1/1+1=0.30685282中去掉
因此,对于id为3、8、10的文档,此公式的结果为1+log3/3+1=0.71231794,您将在id为3、8、10的文档下的要点中看到此值。
当您比较每个单独碎片的文档相关性时,除了id为1的文档外,这些文档具有相同的numDocs和DOCFREQ,这两个搜索词都匹配,因此具有另一相关性[1]:0.35328037[10,8,3]:0.053425744[9,4,6,2,7]:0.046131223[5]:0.0208632。
在此考虑之后,将达到所创建字段的顺序。看看相关性评分背后的理论:在我更仔细地阅读ES文档之后,我发现我可以解决启用dfs\u查询\u然后\u获取查询模式的问题。我知道这不是一个好的做法,但对于大量的数据来说,这是有帮助的
一些策略可以为最新的项目启用此模式,当ES数据库增长时,更改默认模式并继续工作。打印分数;我敢打赌他们在2-9的比赛中是不同的。接下来的问题是为什么?你的文档在你的查询中得分是多少?默认情况下,评分包括文档时间戳之类的内容,因此这可能会影响您的结果。是的,每个文档的评分不同:1:sort:[0.35328037138853440000]10:sort:[0.053425744138931200000]8:sort:[0.0534257441389139200000]3:sort:[0.0534257441388707200000]9:sort:[0.04613122231389225600000]7:sort:[0.0461312223138905280000]6:排序:[0.0461312223138896400000]4:排序:[0.0461312223138879600000]2:排序:[0.04613122231388620800000]5:排序:[0.0208063213888000000]@OllyCruickshank我真的不知道,我该怎么办?我的意思是该查询的结果分数是之前的答案,我不知道我是否需要做其他事情。请让我们用:GET/clamour\u develope/u search解释计算分数?解释然后键入你的查询……也许你能找到ES将如何生成结果。我添加跟踪分数:true且无任何变化,顺序相同。正如我之前在评论中所说,在全文搜索中,顺序是字典式的。您需要指定一个数字字段进行排序。如果不这样做,您将始终获得问题中描述的顺序。排序字符串和排序数字是不同的排序算法!我如果你在一些文档示例中添加一个要点,这样我们就可以重现该场景,我们可能会为你提供更多帮助。hi@eliasah感谢你的快速回答和帮助,这里是一个要点,其中包含批量插入正文和我使用的查询的设置映射信息,这样你就可以重新创建该场景,非常感谢批量插入不是json!可以吗你能处理这个plz吗?我更新了要点,你可以按感觉执行并检查结果谢谢@s.kwiotek我对它的工作原理有了更多的了解,现在的问题是,如果我希望顺序是1,10,9,8,7,6,5,4,3,2,我该怎么做,因为创建日期应该比反向文档频率更重要