C# 如何为MongoDB嵌入式文档的addresses.city属性创建文本索引
问题原因
你当前的索引创建代码存在两个核心问题:
- 你为整个
Addresses数组创建了文本索引,没有指定到数组嵌套的city字段,导致查询无法匹配到城市字段的内容 - 你调用了异步方法
CreateOneAsync但没有等待执行完成,可能出现索引还未创建完成就执行查询的情况,导致索引不生效
解决方案
1. 先清理旧索引
先连接到MongoDB,执行以下命令删除之前创建的错误文本索引:
db.users.dropIndex("addresses_text")
如果不确定旧索引名称,可以执行db.users.getIndexes()查看所有索引,找到key包含text的对应索引名称删除即可。
2. 修正索引创建代码
// 异步写法推荐 public async Task CreateIndexesAsync() { try { // 指定为Addresses数组下所有元素的City字段创建文本索引 var indexKeys = Builders<Users>.IndexKeys.Text(_ => _.Addresses.ElementAt(-1).City); var indexModel = new CreateIndexModel<Users>(indexKeys); var collection = _mongoDb.GetCollection<Users>("users"); // 等待索引创建完成 await collection.Indexes.CreateOneAsync(indexModel); } catch (Exception ex) { throw; } } // 如果需要同步写法,直接调用同步方法即可 public void CreateIndexes() { try { var indexKeys = Builders<Users>.IndexKeys.Text(_ => _.Addresses.ElementAt(-1).City); var indexModel = new CreateIndexModel<Users>(indexKeys); var collection = _mongoDb.GetCollection<Users>("users"); collection.Indexes.CreateOne(indexModel); } catch (Exception ex) { throw; } }
代码中ElementAt(-1)是MongoDB C#驱动的固定写法,代表匹配数组内的所有元素的对应字段。
3. 查询注意事项
MongoDB默认的文本索引是全文分词匹配,只会匹配完整的分词结果:
- 如果你搜索完整关键词
Canada,用你现有的Text(searchTerm)查询可以正常命中结果 - 如果你需要实现前缀匹配(比如输入
Cana就匹配到Canada),不能直接用文本查询,可以改用正则过滤且前缀匹配的写法,示例:
var filter = builder.Regex(_ => _.Addresses.ElementAt(-1).City, new BsonRegularExpression($"^{searchTerm}", "i"));
这种前缀正则查询可以正常命中索引,i参数代表忽略大小写。
内容的提问来源于stack exchange,提问作者Samsul Hoque
相关产品推荐
相关产品推荐

