前一段时间,我为Web应用程序设置了搜索索引。要求之一是返回搜索词的部分匹配项。例如,搜索Joh
应该找到John Doe
。实现此目的最直接的方法是在将查询发布到Azure搜索之前,在每个搜索词后附加一个*
。因此,如果用户键入Joh
,我们实际上会要求Azure搜索来搜索Joh*
。
此方法的局限性是Joh*
的所有匹配项都具有相同的搜索分数。因此,有时部分匹配的结果似乎比完全匹配的结果高。这是documented behavior,所以我想我对此无能为力。或者可以吗?
虽然我目前的返回部分匹配的方式似乎很简单,但实际上它已经足够好了,所以我没关系找出如何正确解决问题的方法。现在我有时间研究它,而我的直觉是必须有一种“适当”的方法来做到这一点。我到处都读过“ ngrams”一词,它似乎是解决方案的一部分。经过数小时的黑客攻击后,我可能会找到一个可行的解决方案,但是如果有任何“标准方法”来实现我想要的功能,我宁愿遵循这种方式,而不是使用自家的黑客工具。因此,这个问题。
所以我的问题是:是否有一种标准方法可以在Azure搜索中检索部分匹配,同时为完全匹配提供更高的分数?我应该如何更改下面的代码以使Azure搜索返回搜索我需要结果吗?
由Azure API返回的索引定义:
{
"name": "test-index",
"defaultScoringProfile": null,
"fields": [
{
"name": "id",
"type": "Edm.String",
"searchable": false,
"filterable": true,
"retrievable": true,
"sortable": false,
"facetable": false,
"key": true,
"indexAnalyzer": null,
"searchAnalyzer": null,
"analyzer": null,
"synonymMaps": []
},
{
"name": "name",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"retrievable": true,
"sortable": true,
"facetable": false,
"key": false,
"indexAnalyzer": null,
"searchAnalyzer": null,
"analyzer": null,
"synonymMaps": []
}
],
"scoringProfiles": [],
"corsOptions": null,
"suggesters": [],
"analyzers": [],
"tokenizers": [],
"tokenFilters": [],
"charFilters": []
}
发布到Azure API的文档:
{
"value": [
{
"@search.action": "mergeOrUpload",
"id": "1",
"name": "Joh Doe"
},
{
"@search.action": "mergeOrUpload",
"id": "2",
"name": "John Doe"
}
]
}
发布到Azure API的搜索查询:
{
search: "Joh*"
}
结果,精确匹配出现在第二位,而我们希望它出现在第一位:
{
"value": [
{
"@search.score": 1,
"id": "2",
"name": "John Doe"
},
{
"@search.score": 1,
"id": "1",
"name": "Joh Doe"
}
]
}
答案 0 :(得分:2)
这是一个很好的问题,感谢您提供详细的说明。实现此目的的最简单方法是对实际术语使用术语增强,并将其与通配符查询结合使用。您可以将帖子中的查询修改为-
search=Joh^10 OR Joh*&queryType=full
这会使与Joh匹配的文档得分更高。如果您有更复杂的要求,则可以考虑使用ngram构建自定义分析器以对其进行搜索以支持部分搜索。