首页 > 解决方案 > C# MongoDB 2. 查找比较其字段的文档:不支持的过滤器

问题描述

我正在尝试以这种方式从 MongoDB 获取文档:

    public async Task<IEnumerable<UnitModel>> GetUnits(string race)
    {
        var units = collection.Aggregate().Match(x => x.Race == race && 
            (x.Attack < x.Def1 || x.Attack < x.Def2) && 
            (x.UnitType == UnitType.Warrior || x.UnitType == UnitType.Archer));
        return await units.ToListAsync();
    }

但是会出现以下错误:

Unsupported filter: ({document}{attack} < {document}{def1}). 

将 Where 与相同的谓词一起使用会导致相同的结果。我做错了什么?

更新

据我了解,C# 驱动程序无法转换此查询。现在我正在尝试使用管道。首先,我在 shell 中测试了查询,它可以工作:

db.units.aggregate([
    {
        $addFields: {
            cDiff: {$cmp: ['$attack','$def1']},
            iDiff: {$cmp: ['$attack','$def2']}
        }
    },
    {
        $match: {
            $and: [
                {race: "elf"},
                {$or: [
                    {
                        cDiff:{$eq:-1}
                    },
                    {
                        iDiff:{$eq:-1}
                    }
                ]},
                {$or: [{
                    "unitType": "Warrior"
                },
                {
                    "unitType": "Archer"
                }]}
            ]
        }
    }
]).pretty()

现在我坚持将其转换为 C#:

    public async Task<IEnumerable<UnitModel>> GetDeffenceUnits(Race race)
    {
        PipelineDefinition<UnitModel, UnitModel> pipeline = new BsonDocument[]
        {
            new BsonDocument{
                { "$addFields", new BsonDocument
                    {
                        { "iDiff:", new BsonDocument { { "$cmp", new BsonArray { "$attack", "$def1" } } } },
                        { "cDiff:", new BsonDocument { { "$cmp", new BsonArray { "$attack", "$def2" } } } }
                    }
                }
            },
            new BsonDocument
            {
                {
                    "$match", new BsonDocument
                    {
                        {
                            "$and", new BsonArray
                            {
                                new BsonDocument
                                {
                                    { "race", race.GetEnumDisplayName() }
                                },
                                new BsonDocument
                                {
                                    {
                                        "$or", new BsonArray
                                        {
                                            new BsonDocument
                                            {
                                                { "iDiff", new BsonDocument { { "$eq", -1 } } }
                                            },
                                            new BsonDocument
                                            {
                                                { "cDiff", new BsonDocument { { "$eq", -1 } } }
                                            }
                                        }
                                    }
                                },
                                new BsonDocument
                                {
                                    {
                                        "$or", new BsonArray
                                        {
                                            new BsonDocument
                                            {
                                                { "unitType", UnitType.Warrior.GetEnumDisplayName() }
                                            },
                                            new BsonDocument
                                            {
                                                { "unitType", UnitType.Warrior.GetEnumDisplayName() }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        };

        var units = collection.Aggregate(pipeline);                
        return await units.ToListAsync();
    }

此查询返回一个空列表。我错过了什么?


更新 2 添加 UnitModel:

[BsonIgnoreExtraElements]
public class UnitModel
{
    public string Name { get; set; }
    // enum
    public Race Race { get; set; }
    public double Expenses { get; set; }
    public double Speed { get; set; }
    public double Capacity { get; set; }
    public double Attack { get; set; }
    public double Def1 { get; set; }
    public double Def2 { get; set; }
    // enum
    public UnitType UnitType { get; set; }
    public ResourcesModel TrainingCost { get; set; }
    public ResourcesModel ResearchCost { get; set; }
    public TimeSpan ResearchTime { get; set; }
    public TimeSpan TrainingTime { get; set; }
}

public class ResourcesModel
{
    public int Wood { get; set; }
    public int Gold { get; set; }
    public int Iron { get; set; }
}

更新 3 试图查看 mongodb 请求:

        var units = collection.Aggregate(pipeline);
        var queryToMongo = units.ToString();
        return await units.ToListAsync(); 

更新 4 约定包:

        var packEnum = new ConventionPack
        {
            new EnumRepresentationConvention(BsonType.String)
        };
        ConventionRegistry.Register("EnumStringConvention", packEnum, t => true);

        var packCamelCase = new ConventionPack
        {
            new CamelCaseElementNameConvention()
        };
        ConventionRegistry.Register("camel case",
                                    packCamelCase,
                                    t => t.FullName.StartsWith("TTB.DAL.Models"));

标签: c#asp.net-coremongodb-querymongodb-.net-driver

解决方案


你知道,这真的很尴尬......当我将我的 shell 查询复制到 C# 时,我忘记删除 iDiff 和 cDiff 之后的冒号。在我删除它们后,查询运行良好。


推荐阅读