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

MongoDB C#中.Match()与.Lookup()方法使用问题求助

MongoDB查询关联邻市数据的语法错误排查

问题描述

作为软件开发新手,正在学习MongoDB,当前遇到技术问题:需要在项目中查询选中城市信息时,同时获取其邻市的车牌代码(PlakaCode)及城市名称。调研后得知需使用.Match()和.Lookup()方法,但编写代码时持续出现语法错误,不确定代码结构是否正确,请求协助排查。


实体类定义

public class RelationalCityViewModel
{
    [BsonId]
    public ObjectId Id { get; set; }
    public string PlakaCode { get; set; }
    public string Name { get; set; }
    public int OrderNo { get; set; }
    public bool IsDelete { get; set; }
    public int CountryId { get; set; }
    public string Url { get; set; }
    public List<NeighborCity> NeighborCities { get; set; }
}
public class RelationalCityCreateViewModel
{
    public string PlakaCode { get; set; }
    public string Name { get; set; }
    public int OrderNo { get; set; }
    public int CountryId { get; set; }
    public string Url { get; set; }
    public List<NeighborCity> NeighborCities { get; set; }
}

public class NeighborCity
{
    [BsonId]
    public ObjectId Id { get; set; }
    public string PlakaCode { get; set; }
    public string Name { get; set; }
    public bool IsDelete { get; set; }
}

查询方法代码

public async Task<BsonDocument> GetDataByIdWithFilter(FilterDefinition<BsonDocument>? filter, ObjectId id, RelationalCityViewModel relationalCityViewModel)
{
    var result = _mongoDbCollection.Aggregate()
                    .Match(filter)
                    .Lookup(_mongoDbCollection,
                            relationalCityViewModel.NeighborCities.FirstOrDefault().Id,
                            relationalCityViewModel.Id,
                            (RelationalCityViewModel city, IEnumerable<RelationalCityViewModel> neighbors) => new
                            {
                                city.Name,
                                city.PlakaCode,
                                NeighborCities = neighbors.Select(n => new
                                {
                                    n.Name,
                                    n.PlakaCode
                                })
                            }
                    );


    return result;
}

问题排查与修正

你的代码存在3个核心问题,导致语法和逻辑错误:

  1. Lookup参数逻辑错误
    MongoDB C#驱动的.Lookup()需要传入字段映射关系,而非具体的ID值。你直接使用relationalCityViewModel.NeighborCities.FirstOrDefault().Id(方法参数的具体值)替代了聚合管道中当前文档的字段路径,完全不符合Lookup的关联逻辑。

  2. 类型不匹配
    方法返回类型是BsonDocument,但聚合操作返回的是匿名类型的集合,类型无法兼容,会触发编译错误。

  3. 异步操作未正确处理
    方法标记了async,但未使用await调用聚合的异步方法,既会触发编译警告,也会导致逻辑上的错误。

修正方案1:分步查询(更直观)

假设_mongoDbCollection是IMongoCollection<RelationalCityViewModel>类型,分步查询逻辑更清晰:

public async Task<RelationalCityViewModel> GetCityWithNeighbors(ObjectId cityId)
{
    // 1. 获取目标城市
    var targetCity = await _mongoDbCollection.Find(c => c.Id == cityId && !c.IsDelete).FirstOrDefaultAsync();
    if (targetCity == null) return null;

    // 2. 提取邻市ID并查询对应数据
    var neighborIds = targetCity.NeighborCities.Select(n => n.Id).ToList();
    var neighborCities = await _mongoDbCollection.Find(c => neighborIds.Contains(c.Id) && !c.IsDelete)
        .Project(c => new NeighborCity
        {
            Name = c.Name,
            PlakaCode = c.PlakaCode
        })
        .ToListAsync();

    // 3. 组装结果
    targetCity.NeighborCities = neighborCities;
    return targetCity;
}

修正方案2:聚合管道Lookup实现

如果一定要用聚合管道完成,正确的写法如下:

public async Task<RelationalCityViewModel> GetCityWithNeighborsByAggregate(ObjectId cityId)
{
    var result = await _mongoDbCollection.Aggregate()
        // 匹配目标城市
        .Match(c => c.Id == cityId && !c.IsDelete)
        // Lookup关联邻市:本地字段是邻市ID列表,关联集合的主键_id
        .Lookup(
            foreignCollection: _mongoDbCollection,
            localField: c => c.NeighborCities.Select(n => n.Id),
            foreignField: c => c.Id,
            @as: (RelationalCityViewModel c) => c.NeighborCities
        )
        // 投影只保留需要的字段
        .Project(c => new RelationalCityViewModel
        {
            Id = c.Id,
            Name = c.Name,
            PlakaCode = c.PlakaCode,
            NeighborCities = c.NeighborCities.Select(n => new NeighborCity
            {
                Name = n.Name,
                PlakaCode = n.PlakaCode
            }).ToList()
        })
        .FirstOrDefaultAsync();

    return result;
}

关键注意点

  • 确保集合泛型类型为RelationalCityViewModel,而非BsonDocument,利用强类型映射避免转换错误。
  • Lookup的localField必须是当前文档中存储关联ID的字段路径,foreignField是关联集合的匹配字段(这里是主键_id)。
  • 聚合操作必须配合await调用异步方法,返回类型要与聚合结果匹配。

内容的提问来源于stack exchange,提问作者Kerem Aluç

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:13:23