基于CosmosDB的Azure Search如何实现有序多词包含搜索?
搞定Azure Search里跨词的顺序子串匹配需求
我明白你想要的效果——就是要找出那些包含"azy do"这类跨词子串的文档(比如"lazy dog"),还得保证顺序不能反,比如"dog lazy"这种就不能匹配。这确实是Azure Search默认的词项索引机制下容易卡壳的点,下面给你两个靠谱的解决办法:
方案一:用Lucene Span查询(首推)
Azure Search支持Lucene语法里的Span查询,这玩意儿能精准控制词的位置和顺序,正好解决你的问题。你可以这么写查询:
spanNear([spanRegex(".*azy.*"), spanRegex(".*do.*")], 1, true)
给你拆解下参数:
spanRegex(".*azy.*"):找任何包含"azy"的词,比如"lazy"、"crazy"都能命中spanRegex(".*do.*"):同理,找任何包含"do"的词,比如"dog"、"dot"1:两个匹配到的词之间最多允许隔1个词(这里设1是因为"lazy"和"dog"之间没其他词,要是你允许中间有词,就调大这个数)true:强制要求第一个词必须在第二个词前面,这样就直接排除了"dog lazy"这种逆序的情况
这么写既符合你的顺序要求,又能准确匹配到跨词的子串,完美~
方案二:自定义Ngram分析器(适合纯子串场景)
如果你需要的是更纯粹的连续字符匹配(不管是不是在词里),可以给索引加个自定义的Ngram分析器,把文本拆成各种短字符片段来索引:
- 先在索引定义里加这个分析器:
"analyzers": [ { "name": "ngram_analyzer", "@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer", "tokenizer": "standard", "tokenFilters": [ { "@odata.type": "#Microsoft.Azure.Search.NGramTokenFilter", "minGram": 3, "maxGram": 10 } ] } ]
- 把你要查询的字段设置成用这个分析器:
"fields": [ { "name": "your_target_field", "type": "Edm.String", "searchable": true, "analyzer": "ngram_analyzer" } ]
- 之后直接搜
"azy do"就能匹配所有包含这个连续子串的文档,跨词的情况也能命中。
不过这个方法有个小缺点:索引会变大不少,而且可能会匹配一些你不想要的结果(比如"azyx doxy"这种),所以更适合对精确性要求没那么高,但就想要纯子串匹配的场景。
为啥之前的方法都不行?
- 直接搜
"azy do":默认分析器会把它拆成"azy"和"do"两个独立词,但你的文档里只有"lazy"和"dog",没有完全匹配的词,所以查不到结果。 - 用
/.*azy do.*/正则:Azure Search的正则默认只能匹配单个词,没法跨词找,这个正则只会找单个词里包含"azy do"的情况,自然没用。 /.*azy.*/ AND /.*do.*/:这只是逻辑“且”,不管词的顺序,所以"dog lazy"这种逆序的也会被匹配到,不符合你的要求。
内容的提问来源于stack exchange,提问作者Akash Yadav
相关产品推荐
相关产品推荐

