在 Azure 搜索中返回部分匹配项

aoc*_*via 5 azure azure-cognitive-search

不久前,我为一个网络应用程序设置了一个搜索索引。要求之一是返回搜索词的部分匹配。例如,搜索Joh应该找到John Doe. 实现此目的的最直接方法是在*将查询发布到 Azure 搜索之前将 附加到每个搜索词。因此,如果用户键入Joh,我们实际上会要求 Azure 搜索进行搜索Joh*

这种方法的一个限制是所有匹配项都Joh*具有相同的搜索分数。因此,有时部分匹配的结果会比完全匹配的结果更高。这是有记录的行为,所以我想我对此无能为力。或者我可以吗?

虽然我目前返回部分匹配的方法看起来像是一种黑客攻击,但它在实践中效果很好,我并不关心如何正确解决问题。现在我有时间研究它,我的直觉告诉我必须有一个“正确”的方法来做到这一点。我到处读过“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": []
}
Run Code Online (Sandbox Code Playgroud)

发布到 Azure API 的文档:

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "id": "1",
            "name": "Joh Doe"
        },
        {
            "@search.action": "mergeOrUpload",
            "id": "2",
            "name": "John Doe"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

搜索查询,发布到 Azure API:

{
    search: "Joh*"
}
Run Code Online (Sandbox Code Playgroud)

结果,精确匹配出现在第二位,而我们希望它出现在第一位:

{
    "value": [
        {
            "@search.score": 1,
            "id": "2",
            "name": "John Doe"
        },
        {
            "@search.score": 1,
            "id": "1",
            "name": "Joh Doe"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

小智 7

这是一个非常好的问题,感谢您提供详细的解释。实现这一目标的最简单方法是对实际术语使用术语提升并将其与通配符查询结合起来。您可以将帖子中的查询修改为 -

search=Joh^10 OR Joh*&queryType=full
Run Code Online (Sandbox Code Playgroud)

这将为与 Joh 完全匹配的文档评分更高。如果您有更复杂的需求,您可以考虑使用 ngram 构建自定义分析器来搜索它们以支持部分搜索。