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

Returning partial matches in Azure Search

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

此方法的一个限制是 Joh* 的所有匹配项都具有相同的搜索分数。因此,有时部分匹配在结果中的显示度高于完全匹配。这是 documented behavior,所以我想我对此无能为力。或者我可以吗?

虽然我目前 return 部分匹配的方法看起来像是 hack,但在实践中效果很好,我并不关心如何正确解决问题。现在我有时间研究它,我的直觉告诉我必须有一种 "proper" 方法来做到这一点。我在这里和那里读过 "ngrams" 这个词,它似乎是解决方案的一部分。经过几个小时的黑客攻击后,我可能会找到一个可行的解决方案,但如果有任何 "standard way" 可以实现我想要的,我宁愿遵循这条道路而不是使用本土黑客。因此这个问题。

所以我的问题是:是否有一种标准方法可以在 Azure 搜索中检索部分匹配项,同时为完全匹配项提供更高的分数?我应该如何更改下面的代码以使Azure 搜索 return 我需要的搜索结果?

代码

索引定义,由 Azure return编辑 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"
        }
    ]
}

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

search=Joh^10 OR Joh*&queryType=full

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