You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Cognitive Search含连字符字符串与通配符兼容搜索问题

Azure Cognitive Search 特殊字符搜索与前缀匹配兼容方案

核心问题梳理

  • 为解决.docx后缀前单词搜索评分低的问题,全局给搜索词加*实现前缀匹配,但含连字符等特殊字符的词汇加*后无法匹配
  • 用引号包裹精确匹配("search-term")单独有效,但加*无结果;正则查询(/search-term.*/)匹配结果评分偏低

可行解决方案

1. 给文件名字段配置自定义分析器(推荐)

问题根源在于默认分析器会拆分含连字符的词汇,同时.docx后缀干扰前缀匹配。针对metadata_storage_name字段创建自定义分析器,提前处理文件名:

步骤1:定义自定义分析器

更新索引的分析器配置:

{
  "analyzers": [
    {
      "name": "filename_prefix_analyzer",
      "@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
      "tokenizer": "keyword_v2", // 保留完整字符串不拆分
      "tokenFilters": [
        "lowercase", // 统一小写,避免大小写敏感
        {
          "@odata.type": "#Microsoft.Azure.Search.PatternReplaceTokenFilter",
          "pattern": "\\.(docx|doc)$", // 移除常见文档后缀
          "replacement": ""
        },
        {
          "@odata.type": "#Microsoft.Azure.Search.EdgeNGramTokenFilter",
          "minGram": 2,
          "maxGram": 50,
          "side": "front" // 生成前缀ngram,支持前缀匹配
        }
      ]
    }
  ]
}

步骤2:绑定字段到分析器

修改metadata_storage_name字段的配置:

{
  "name": "metadata_storage_name",
  "type": "Edm.String",
  "searchable": true,
  "filterable": true,
  "analyzer": "filename_prefix_analyzer"
}

效果

  • 无需在搜索词后加*,直接搜索search-term或search都能匹配search-term.docx
  • 特殊字符不会被拆分,精确保留原文件名结构

2. 查询时动态处理搜索词

保留全局前缀匹配的同时,对含特殊字符的词汇单独处理,避免*破坏精确匹配:

修改代码中的查询逻辑:

public ActionResult<DcFolder.DcFolderDto> GetSearchResults(string query) {
    // 转义查询中的特殊字符,避免语法错误
    string escapedQuery = query.Replace("'", "''");
    bool hasSpecialChars = escapedQuery.Any(c => !char.IsLetterOrDigit(c));

    if (hasSpecialChars)
    {
        // 对含特殊字符的词汇,同时启用精确前缀匹配和普通前缀匹配
        query = $"search.ismatch('\"{escapedQuery}*\"', 'metadata_storage_name', 'full', 'any') OR {escapedQuery}*";
    }
    else
    {
        query = escapedQuery + "*";
    }

    Uri searchEndpointUri = new(SEARCH_ENDPOINT);
    SearchClient client = new(
        searchEndpointUri,
        SEARCH_INDEX_NAME,
        new AzureKeyCredential(SEARCH_KEY));

    var options = new SearchOptions {
        SearchFields = { "metadata_storage_name", "content" },
        QueryType = Azure.Search.Documents.Models.SearchQueryType.Full,
        SearchMode = Azure.Search.Documents.Models.SearchMode.Any,
    };

    var search = client.Search<DcFolder.DcFolderDto>(query, options, default);
    var document = search.GetRawResponse().Content.ToString();
    dynamic jsonObject = JsonConvert.DeserializeObject(document);

    return Ok(jsonObject);
}

说明

  • 用search.ismatch函数针对文件名字段做精确前缀匹配,避免特殊字符被拆分
  • 保留普通前缀匹配逻辑,兼容不含特殊字符的搜索词

3. 优化正则查询的评分

如果坚持使用正则查询,通过权重提升(^)提高匹配结果的评分:

修改查询构造逻辑:

public ActionResult<DcFolder.DcFolderDto> GetSearchResults(string query) {
    // 转义正则中的特殊字符
    string regexQuery = Regex.Escape(query);
    // 同时启用正则前缀匹配(加权)和普通前缀匹配
    query = $"/{regexQuery}.*/^5 OR {query}*";

    Uri searchEndpointUri = new(SEARCH_ENDPOINT);
    SearchClient client = new(
        searchEndpointUri,
        SEARCH_INDEX_NAME,
        new AzureKeyCredential(SEARCH_KEY));

    var options = new SearchOptions {
        SearchFields = { "metadata_storage_name", "content" },
        QueryType = Azure.Search.Documents.Models.SearchQueryType.Full,
        SearchMode = Azure.Search.Documents.Models.SearchMode.Any,
    };

    var search = client.Search<DcFolder.DcFolderDto>(query, options, default);
    var document = search.GetRawResponse().Content.ToString();
    dynamic jsonObject = JsonConvert.DeserializeObject(document);

    return Ok(jsonObject);
}

效果

  • 正则匹配的结果会获得5倍权重,解决评分偏低的问题
  • 同时保留普通前缀匹配的功能

内容的提问来源于stack exchange,提问作者hagru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:26:34