我正在尝试以这种方式从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会导致相同的结果。我做错了吗?
UPDATE:
据我了解,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();
}
此查询返回一个空列表。我想念什么?
UPDATE 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; }
}
UPDATE 3试图查看mongodb请求:
var units = collection.Aggregate(pipeline);
var queryToMongo = units.ToString();
return await units.ToListAsync();
UPDATE 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"));
[您知道,这真令人尴尬...当我将shell查询复制到C#时,我忘记在iDiff和cDiff之后删除冒号。在我删除它们之后,查询工作正常。