MongoDB C#查询:按序号提取数组指定元素的问题
解决MongoDB C#驱动单次查询提取数组指定元素的问题
问题原因
你多次调用.Slice()对同一个字段进行投影,MongoDB的投影规则会以最后一次操作覆盖之前的配置,所以最终只返回了最后一次Slice指定的元素。
注意:MongoDB数组是0索引的,你提到的第1、7、15位元素,对应的实际索引为0、6、14,以下方案均以此对应关系为准。
解决方案
方案1:直接通过表达式构造目标数组
代码简洁直观,适合固定提取少量元素的场景:
var projection = Builders<ContentEntity>.Projection .Expression(e => new ContentEntity { Id = e.Id, Lines = new List<string> { e.Lines[0], // 对应第1位元素 e.Lines[6], // 对应第7位元素 e.Lines[14] // 对应第15位元素 } }); var entity = await GetContext(categoryId).ContentEntities .Find(e => e.Id == contentId) .Project<ContentEntity>(projection) .FirstOrDefaultAsync(cancellationToken);
方案2:动态指定索引列表
适合需要动态传入提取索引的场景,灵活性更高:
// 定义要提取的元素索引 var targetIndexes = new[] { 0, 6, 14 }; var projection = Builders<ContentEntity>.Projection .Project(e => new { e.Id, Lines = targetIndexes.Select(idx => e.Lines[idx]) }); var tempResult = await GetContext(categoryId).ContentEntities .Find(e => e.Id == contentId) .Project(projection) .FirstOrDefaultAsync(cancellationToken); // 转换为业务实体类型 var entity = tempResult != null ? new ContentEntity { Id = tempResult.Id, Lines = tempResult.Lines.ToList() } : null;
方案3:使用原生聚合操作符$arrayElemAt
贴近MongoDB原生聚合语法,适合复杂投影场景:
var projection = Builders<ContentEntity>.Projection .Include(e => e.Id) .AddFields(f => f .Add("Lines", new BsonArray { new BsonDocument("$arrayElemAt", new BsonArray { "$Lines", 0 }), new BsonDocument("$arrayElemAt", new BsonArray { "$Lines", 6 }), new BsonDocument("$arrayElemAt", new BsonArray { "$Lines", 14 }) }) ); var entity = await GetContext(categoryId).ContentEntities .Find(e => e.Id == contentId) .Project<ContentEntity>(projection) .FirstOrDefaultAsync(cancellationToken);
内容的提问来源于stack exchange,提问作者Alexey Golinski
相关产品推荐
相关产品推荐

