ARGE集合考虑限制收集查找的数量,即重构,这样您就不必调用 G.LAST()/和 G FiST()/代码>,这比我最初的想法还多;但当然,关键是查询实际上不是在C#中运行的,而是转换为在MongoDB服务器本身上运行的查询。除此之外,当您进行重构时,即在
ARGE集合考虑限制收集查找的数量,即重构,这样您就不必调用 G.LAST()/和 G FiST()/代码>,这比我最初的想法还多;但当然,关键是查询实际上不是在C#中运行的,而是转换为在MongoDB服务器本身上运行的查询。除此之外,当您进行重构时,即在,c#,mongodb,performance,aggregation-framework,C#,Mongodb,Performance,Aggregation Framework,ARGE集合考虑限制收集查找的数量,即重构,这样您就不必调用 G.LAST()/和 G FiST()/代码>,这比我最初的想法还多;但当然,关键是查询实际上不是在C#中运行的,而是转换为在MongoDB服务器本身上运行的查询。除此之外,当您进行重构时,即在匿名方法体中创建局部变量时,驱动程序不支持它;只有lambda表达式是可用的。因此,希望我在C#中的努力将被翻译成与我在shell中运行的JavaScript非常相似的东西。遗憾的是,就我所知,在当前版本中,我们无法直接验证这一点。但是,我将测
ARGE集合考虑限制收集查找的数量,即重构,这样您就不必调用<代码> G.LAST()/<代码>和<代码> G FiST()/代码>,这比我最初的想法还多;但当然,关键是查询实际上不是在C#中运行的,而是转换为在MongoDB服务器本身上运行的查询。除此之外,当您进行重构时,即在匿名方法体中创建局部变量时,驱动程序不支持它;只有lambda表达式是可用的。因此,希望我在C#中的努力将被翻译成与我在shell中运行的JavaScript非常相似的东西。遗憾的是,就我所知,在当前版本中,我们无法直接验证这一点。但是,我将测试是否可以将整个组对象传递给
ProductPositionGroupItem
的构造函数。
{
"_id" : "00000000_20160707",
"TimeStamp" : ISODate("2016-07-08T01:47:00.182+0000"),
"Valor" : "00000000",
"NominalInCertificateCurrency" : -1189575.0,
"NominalInLocalCurrency" : -1287239.0,
"Position" : -15300.0,
"Price" : 77.75,
"ProductName" : "TRACKER CERT. ABC 123",
"At" : ISODate("2016-07-07T00:00:00.000+0000"),
"CurrencyId" : "814"
}
{
"At" : 1,
"Valor" : 1,
"IssueNostro" : 1
}
db.productpositions.aggregate([
{ $match: {
$and: [
{"At": {$gte: ISODate("2016-10-01T00:00:00Z")}},
{"At": {$lte: ISODate("2016-12-31T00:00:00Z")} },
{"Valor": { $in: [...]}}, // about a dozen valors
{"IssueNostro": { $ne: null} }
]
}},
{ $sort: { "At": 1 } },
{ $group: {
"_id": { "Valor": "$Valor", "IssueNostro": "$IssueNostro" },
"CurrencyId": { $last: "$CurrencyId" },
"DescriptionCombo": { $last: "$DescriptionCombo" },
"IssueNostro": { $last: "$IssueNostro" },
"NominalInCertificateCurrency": { $last: "$NominalInCertificateCurrency" },
"NominalInLocalCurrency": { $last: "$NominalInLocalCurrency" },
"PaymentDate": { $last: "$PaymentDate" },
"Position": { $last: "$Position" },
"PositionFirstDate": { $first: "$At" },
"PositionLastDate": { $last: "$At" },
"Price": { $last: "$Price" },
"ProductName": { $last: "$ProductName" },
"RedemptionDate": { $last: "$RedemptionDate" },
"TimeStamp": { $last: "$TimeStamp" },
"Valor": { $last: "$Valor" }
}
},
])
public virtual async Task<IEnumerable<IProductPeriodFee>> GetProductPeriodPositionsAsync(IEnumerable<string> valors, DateTime fromDate, DateTime toDate)
{
var valorArray = valors.ToArray();
using (new SimpleTimer(this, "GetProductPeriodPositionsAsync", new {valorArray, fromDate, toDate}))
{
var @where = CreateWhereExpression(valorArray, fromDate, toDate);
var raw = await GroupAsync(@where,
x => x.At,
x => new ProductPositionKey {Valor = x.Valor, IssueNostro = x.IssueNostro},
g => new ProductPositionGroupItem
{
CurrencyId = g.Last().CurrencyId,
DescriptionCombo = g.Last().DescriptionCombo,
Id = g.Last().Id,
IssueNostro = g.Last().IssueNostro,
NominalInCertificateCurrency = g.Last().NominalInCertificateCurrency,
NominalInLocalCurrency = g.Last().NominalInLocalCurrency,
PaymentDate = g.Last().PaymentDate,
Position = g.Last().Position,
PositionFirstDate = g.First().At,
PositionLastDate = g.Last().At,
Price = g.Last().Price,
ProductName = g.Last().ProductName,
RedemptionDate = g.Last().RedemptionDate,
TimeStamp = g.Last().TimeStamp,
Valor = g.Last().Valor
});
return raw.Select(item => new ProductPeriodFee
{
CurrencyId = item.CurrencyId,
DescriptionCombo = item.DescriptionCombo,
Id = item.Id,
IssueNostro = item.IssueNostro,
NominalInCertCny = (decimal?) item.NominalInCertificateCurrency,
NominalInLocalCurrency = (decimal?) item.NominalInLocalCurrency,
PaymentDate = item.PaymentDate,
PeriodEndDate = toDate,
PeriodStartDate = fromDate,
Position = (decimal?) item.Position,
PositionFirstDate = item.PositionFirstDate,
PositionLastDate = item.PositionLastDate,
Price = (decimal?) item.Price,
ProductName = item.ProductName,
RedemptionDate = item.RedemptionDate,
TimeStamp = item.TimeStamp,
Valor = item.Valor
});
}
}
private static Expression<Func<ProductPositionDataDb, bool>> CreateWhereExpression(IReadOnlyCollection<string> valors, DateTime? from, DateTime? to)
{
// Doing it this incredibly long way around, because the group/select does not work if you include "Enumerable<T>.Contains" in the where clause
var argParam = Expression.Parameter(typeof(ProductPositionDataDb), "x");
var atProp = Expression.Property(argParam, "At");
var atGreaterThan = Expression.GreaterThanOrEqual(atProp, Expression.Constant(from));
var atLessThan = Expression.LessThanOrEqual(atProp, Expression.Constant(to));
var exp = Expression.And(atGreaterThan, atLessThan);
if (valors.Any())
{
var valorProp = Expression.Property(argParam, "Valor");
var valorExp = valors.Select(v => Expression.Equal(valorProp, Expression.Constant(v))).Aggregate(Expression.Or);
exp = Expression.AndAlso(exp, valorExp);
}
var atPropNostro = Expression.Property(argParam, "IssueNostro");
var nostroExp = Expression.NotEqual(atPropNostro, Expression.Constant(null, atPropNostro.Type));
exp = Expression.AndAlso(exp, nostroExp);
return Expression.Lambda<Func<ProductPositionDataDb, bool>>(exp, argParam);
}
public async Task<IEnumerable<TResult>> GroupAsync<TKey, TResult>(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> sort, Expression<Func<T, TKey>> groupBy, Expression<Func<IGrouping<TKey, T>, TResult>> project)
{
return await _mongoCollection.Aggregate(new AggregateOptions {AllowDiskUse = true})
.Match(predicate)
.Sort(Builders<T>.Sort.Ascending(sort))
.Group(groupBy, project)
.ToListAsync();
}
var raw = await Collection.GroupAsync(
x => x.At >= fromDate && x.At <= toDate && valorArray.Contains(x.Valor),
x => x.At,
x => new ProductPositionKey {Valor = x.Valor, IssueNostro = x.IssueNostro},
g => new ProductPositionGroupItem
{
CurrencyId = g.Last().CurrencyId,
DescriptionCombo = g.Last().DescriptionCombo,
Id = g.Last().Id,
IssueNostro = g.Last().IssueNostro,
NominalInCertificateCurrency = g.Last().NominalInCertificateCurrency,
NominalInChf = g.Last().NominalInChf,
PaymentDate = g.Last().PaymentDate,
Position = g.Last().Position,
PositionFirstDate = g.First().At,
PositionLastDate = g.Last().At,
Price = g.Last().Price,
ProductName = g.Last().ProductName,
RedemptionDate = g.Last().RedemptionDate,
Source = g.Last().Source,
TimeStamp = g.Last().TimeStamp,
Valor = g.Last().Valor
});