Я борюсь с группировкой, используя RavenDB и LuceneQuery.
У меня всегда было впечатление, что IEnumerable оценивается только при вызове ToArray() и т. д.
Следующий запрос был разделен на две части для ясности.
Я бы не ожидал, что запрос будет оцениваться до тех пор, пока ToArray() не будет вызван для totalledBalanceList, я ожидаю, что группировка будет выполнена на сервере для всех данных. Однако фактический результат зависит от количества элементов, указанных в .Take(). Без Take(1024) возвращаются результаты для 128 элементов по умолчанию.
Мне нужно иметь возможность выполнить группировку по всему набору данных.
using (var session = MvcApplication.RavenSession)
{
var computedBalanceList =
from c in session.Advanced.LuceneQuery<Journal, Ledger_ByDateAndDebitIdAndCreditIdAndValues>()
.Where(parameters)
.OrderBy(c => c.DateAsString).Take(1024)
select new LedgerBalanceDto
{
Account = account,
Name = queryName,
Debits = c.DebitId == account.Id
? c.DebitValue
: 0,
Credits = (c.CreditId == account.Id)
? c.CreditValue
: 0,
Currency = (c.DebitId == account.Id) ? c.DebitCurrency : c.CreditCurrency,
CurrencySymbol = (c.DebitId == account.Id) ? c.DebitCurrencySymbol : c.CreditCurrencySymbol,
};
var totalledBalanceList =
from balance in computedBalanceList
group new {balance.Debits, balance.Credits} by new {balance.Currency, balance.CurrencySymbol}
into grouping
select new LedgerBalanceDto
{
Account = account,
Currency = grouping.Key.Currency,
CurrencySymbol = grouping.Key.CurrencySymbol,
Debits = grouping.Sum(c => c.Debits),
Credits = grouping.Sum(c => c.Credits),
Name = queryName
};
return totalledBalanceList;
И индекс:
public class Ledger_ByDateAndDebitIdAndCreditIdAndValues:AbstractIndexCreationTask<Journal>
{
public Ledger_ByDateAndDebitIdAndCreditIdAndValues()
{
Map = journals => from c in journals
select new {c.Date,c.DateAsString, c.DebitId, c.CreditId,c.DebitValue,c.CreditValue};
Index(x=>x.Date,FieldIndexing.Analyzed);
Index(x=>x.DateAsString,FieldIndexing.Analyzed);
Index(x=>x.DebitId,FieldIndexing.Analyzed);
Index(x=>x.CreditId,FieldIndexing.Analyzed);
Index(x=>x.DebitValue,FieldIndexing.Analyzed);
Index(x=>x.CreditValue,FieldIndexing.Analyzed);
Sort(x=>x.DateAsString,SortOptions.String);
}
}
Я также переписал запрос так, чтобы группировка происходила «вне» фильтра, но я получаю точно такие же результаты, а именно результат зависит от Take().
var totalledBalanceList = from balance in
from c in query
.Where(parameters)
.OrderBy(c => c.DateAsString)
select new LedgerBalanceDto
{
Account = account,
Name = queryName,
Debits = c.DebitId == account.Id
? c.DebitValue
: 0,
Credits = (c.CreditId == account.Id)
? c.CreditValue
: 0,
Currency = (c.DebitId == account.Id) ? c.DebitCurrency : c.CreditCurrency,
CurrencySymbol = (c.DebitId == account.Id) ? c.DebitCurrencySymbol : c.CreditCurrencySymbol,
}
group new {balance.Debits, balance.Credits} by new {balance.Currency, balance.CurrencySymbol}
into grouping
select new LedgerBalanceDto
{
Account = account,
Currency = grouping.Key.Currency,
CurrencySymbol = grouping.Key.CurrencySymbol,
Debits = grouping.Sum(c => c.Debits),
Credits = grouping.Sum(c => c.Credits),
Name = queryName
};
return totalledBalanceList;
Любые мысли по этому поводу будут высоко оценены.
Часть класса журнала:
public class Journal
{
public string Id { get; set; }
public string DebitId{get;set;}
public string CreditId{get;set;}
public decimal? ExchangeRate { get; set; }
public decimal CreditValue {get;set;}
public decimal DebitValue {get;set;}
public string DebitCurrency {get;set;}
public string CreditCurrency {get;set;}
public decimal Nett
{
get { return _nett; }
set
{
_nett = value;
CreditValue = Math.Round(Nett, 2);
DebitValue = Math.Round(Nett * (ExchangeRate ?? 1), 2);
}
}
etc ...
}
Пример данных IEnumerable<Journal>:
Id DebitId CreditId Nett ExchangeRate DbCurr CrCurr DbVal CrVal
1 Expense1 Bank 100 2.03 BRL USD 203.00 100.00
2 Expense2 Bank 50 null USD USD 50.00 50.00
3 Bank Client1 300 null USD USD 300.00 300.00
4 Stock Bank 300 null USD USD 300.00 300.00
Например, когда я запрашиваю банк, я хочу иметь возможность суммировать DbVal и CrVal и вычислять баланс, но для этого мне нужно обнулить либо одно, либо другое (согласно запросу).