如何基于Azure Cosmos DB实现自动建议功能(小数据量场景)
在Azure Cosmos DB (NoSQL) 中实现轻量自动建议方案
针对你几千条数据的场景,无需依赖外部搜索服务,直接基于Cosmos DB自身的索引和查询能力就能实现高效的自动建议功能,以下是具体步骤:
一、优化数据存储结构
提前对需要提供自动建议的字段做预处理,提升查询效率:
- 统一大小写:将目标字段(如商品名、标题)转换为小写存储,避免大小写敏感导致的匹配遗漏,在.NET Core同步SQL数据时完成此处理。
- 生成词元数组(可选):如果需要支持多词前缀匹配(比如输入"cos"能匹配"Azure Cosmos DB"),可以生成包含所有可能词组合的数组字段。例如将"Azure Cosmos DB"转换为
["azure", "cosmos", "db", "azure cosmos", "cosmos db", "azure cosmos db"],存储为searchTerms字段。
二、配置Cosmos DB索引策略
针对目标字段配置精准的索引,确保前缀匹配查询能高效执行:
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*", "indexes": [] }, { "path": "/productName/?", "indexes": [ { "kind": "Range", "dataType": "String", "precision": -1 } ] }, { "path": "/searchTerms/*", "indexes": [ { "kind": "Range", "dataType": "String", "precision": -1 } ] } ], "excludedPaths": [] }
说明:
precision: -1表示使用最大精度的范围索引,能完美支持STARTSWITH这类前缀查询。
三、实现自动建议查询
根据你的需求选择以下两种方案:
方案1:基础前缀匹配(适合单字段前缀场景)
直接通过STARTSWITH匹配目标字段的前缀,返回去重后的结果:
Cosmos DB SQL查询语句
SELECT DISTINCT c.productName FROM c WHERE STARTSWITH(LOWER(c.productName), LOWER(@prefix)) ORDER BY c.productName OFFSET 0 LIMIT 10
.NET Core代码示例
var prefix = "azu"; // 用户输入的前缀 var query = new QueryDefinition( "SELECT DISTINCT c.productName FROM c WHERE STARTSWITH(LOWER(c.productName), LOWER(@prefix)) ORDER BY c.productName OFFSET 0 LIMIT 10" ).WithParameter("@prefix", prefix); using var iterator = container.GetItemQueryIterator<string>(query); var results = await iterator.ReadNextAsync(); var suggestions = results.Resource.ToList();
方案2:多词前缀匹配(支持中间词前缀)
基于提前生成的searchTerms数组,匹配任意词组合的前缀:
.NET Core同步数据时生成词元数组的代码
public static List<string> GenerateSearchTerms(string input) { var terms = new List<string>(); var words = input.ToLower().Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < words.Length; i++) { var currentTerm = new StringBuilder(); for (int j = i; j < words.Length; j++) { if (currentTerm.Length > 0) currentTerm.Append(' '); currentTerm.Append(words[j]); terms.Add(currentTerm.ToString()); } } return terms.Distinct().ToList(); } // 同步SQL数据到Cosmos DB时调用 var sqlProduct = await sqlContext.Products.FindAsync(id); var cosmosProduct = new Product { Id = sqlProduct.Id.ToString(), ProductName = sqlProduct.Name, SearchTerms = GenerateSearchTerms(sqlProduct.Name) }; await cosmosContainer.UpsertItemAsync(cosmosProduct);
Cosmos DB SQL查询语句
SELECT DISTINCT c.productName FROM c JOIN term IN c.searchTerms WHERE STARTSWITH(term, LOWER(@prefix)) ORDER BY c.productName OFFSET 0 LIMIT 10
四、性能优化建议
- 限制返回数量:通过
LIMIT控制最多返回10-20条建议,减少数据传输量。 - 缓存热门结果:使用.NET内存缓存或Redis缓存高频查询的前缀结果,降低Cosmos DB的查询压力。
- 验证索引使用:在Cosmos DB门户的“查询运行时统计”中确认查询是否命中索引,避免全表扫描。
内容的提问来源于stack exchange,提问作者Ajay Kumar
相关产品推荐
相关产品推荐

