在Azure搜索中返回部分匹配

时间:2019-06-05 08:47:53

标签: azure azure-search

前一段时间,我为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"
        }
    ]
}

1 个答案:

答案 0 :(得分:2)

这是一个很好的问题,感谢您提供详细的说明。实现此目的的最简单方法是对实际术语使用术语增强,并将其与通配符查询结合使用。您可以将帖子中的查询修改为-

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

这会使与Joh匹配的文档得分更高。如果您有更复杂的要求,则可以考虑使用ngram构建自定义分析器以对其进行搜索以支持部分搜索。