2012-08-16 113 views
0

繼我上一個問題When is a groupby query evaluated in RavenDB?後,我決定將數據完全重組爲一種理論上容易查詢的格式。如何將此SQL查詢轉換爲Raven Map/Reduce查詢?

現在已經創建了新的數據結構,我正在努力尋找如何查詢它。

我花了30秒,寫入下面的SQL查詢,給了我完全的結果,我需要:

SELECT  GroupCompanyId, AccountCurrency, AccountName, DATEPART(year, Date) AS Year, 
           (SELECT  SUM(Debit) AS Expr1 
            FROM   Transactions AS T2 
            WHERE  (T1.GroupCompanyId = GroupCompanyId) AND (T1.AccountCurrency = AccountCurrency) AND (T1.AccountName = AccountName) AND (DATEPART(year, 
                  Date) < DATEPART(year, T1.Date))) AS OpeningDebits, 
           (SELECT  SUM(Credit) AS Expr1 
            FROM   Transactions AS T2 
            WHERE  (T1.GroupCompanyId = GroupCompanyId) AND (T1.AccountCurrency = AccountCurrency) AND (T1.AccountName = AccountName) AND (DATEPART(year, 
                  Date) < DATEPART(year, T1.Date))) AS OpeningCredits, SUM(Debit) AS Db, SUM(Credit) AS Cr 
    FROM   Transactions AS T1 
    WHERE  (DATEPART(year, Date) = 2011) 
    GROUP BY GroupCompanyId, AccountCurrency, AccountName, DATEPART(year, Date) 
    ORDER BY GroupCompanyId, AccountCurrency, Year, AccountName 

到目前爲止,我已經得到了的Map/Reduce如下,從工作室似乎給正確的結果 - 即它分解並按日期分組數據。

public Transactions_ByDailyBalance() 
    { 
     Map = transactions => from transaction in transactions 
           select new 
            { 
             transaction.GroupCompanyId, 
             transaction.AccountCurrency, 
             transaction.Account.Category, 
             transaction.Account.GroupType, 
             transaction.AccountId, 
             transaction.AccountName, 
             transaction.Date, 
             transaction.Debit, 
             transaction.Credit, 
            }; 
     Reduce = results => from result in results 
          group result by new 
              { 
               result.GroupCompanyId, 
               result.AccountCurrency, 
               result.Category, 
               result.GroupType, 
               result.AccountId, 
               result.AccountName, 
               result.Date, 
              } 
          into g 
          select new 
            { 
             GroupCompanyId = g.Select(x=>x.GroupCompanyId).FirstOrDefault(), 
             AccountCurrency = g.Select(x=>x.AccountCurrency).FirstOrDefault(), 
             Category=g.Select(x=>x.Category).FirstOrDefault(), 
             GroupType=g.Select(x=>x.GroupType).FirstOrDefault(), 
             AccountId = g.Select(x=>x.AccountId).FirstOrDefault(), 
             AccountName=g.Select(x=>x.AccountName).FirstOrDefault(),           
             Date=g.Select(x=>x.Date).FirstOrDefault(), 
             Debit=g.Sum(x=>x.Debit), 
             Credit=g.Sum(x=>x.Credit) 
            }; 

     Index(x=>x.GroupCompanyId,FieldIndexing.Analyzed); 
     Index(x=>x.AccountCurrency,FieldIndexing.Analyzed); 
     Index(x=>x.Category,FieldIndexing.Analyzed); 
     Index(x=>x.AccountId,FieldIndexing.Analyzed); 
     Index(x=>x.AccountName,FieldIndexing.Analyzed); 
     Index(x=>x.Date,FieldIndexing.Analyzed); 
    } 
}  

不過,我不知道如何一氣呵成查詢數據。 我需要期初餘額以及期末餘額,所以我最終編寫了這個查詢作爲參數的帳戶。從Oren的評論到我之前的問題之後,我將Linq與Lucene查詢混合在一起,重寫了查詢之後,我基本上又結束了混合查詢。

即使我在上面的SQL查詢中顯示我按年篩選,實際上我需要能夠從任何一天確定當前餘額。

 private LedgerBalanceDto GetAccountBalance(BaseAccountCode account, DateTime periodFrom, DateTime periodTo, string queryName) 
    { 
     using (var session = MvcApplication.RavenSession) 
     { 
      var query = session.Query<Transactions_ByDailyBalance.Result, Transactions_ByDailyBalance>() 
       .Where(c=>c.AccountId==account.Id && c.Date>=periodFrom && c.Date<=periodTo) 
       .OrderBy(c=>c.Date) 
       .ToList(); 

      var debits = query.Sum(c => c.Debit); 
      var credits = query.Sum(c => c.Credit); 

      var ledgerBalanceDto = new LedgerBalanceDto 
            { 
             Account = account, 
             Credits = credits, 
             Debits = debits, 
             Currency = account.Currency, 
             CurrencySymbol = account.CurrencySymbol, 
             Name = queryName, 
             PeriodFrom = periodFrom, 
             PeriodTo = periodTo 
            }; 

      return ledgerBalanceDto; 
     } 
    } 

要求的結果:

GroupCompanyId AccountCurrency AccountName Year OpeningDebits OpeningCredits Db Cr 
    Groupcompanies-2 EUR Customer 1 2011 148584.2393 125869.91 10297.6891 28023.98 
    Groupcompanies-2 EUR Customer 2 2011 236818.0054 233671.55 50959.85 54323.38 
    Groupcompanies-2 USD Customer 3 2011 69426.11761 23516.3776 10626.75 0 
    Groupcompanies-2 USD Customer 4 2011 530587.9223 474960.51 97463.544 131497.16 
    Groupcompanies-2 USD Customer 5 2011 29542.391 28850.19 4023.688 4231.388 

任何建議,將不勝感激

傑里米

在回答評論

我基本上結束了做幾乎相同事情。實際上,我寫了一個只有兩次點擊的指數 - 一次是期初餘額,一次是期末餘額。這幾乎是即時的按帳戶名稱,類別等分組。

但是我現在的問題是獲得個人帳戶的每日運行餘額。如果我將賬戶和期間的所有數據都記下來,這不是問題 - 我可以將餘額彙總到客戶端,但是,當數據被分頁時,借記和貸項按日期和標識分組時,分頁截止日期,所以開始/結束餘額是不正確的。

Page 1 

Opening balance until 26/7/12 = 0 

25/7/12 Acct1  Db 100  Cr 0  Bal +100 Runn Bal +100 
26/7/12 Acct1  Db 100  Cr 0  Bal +100 Runn Bal +200 
26/7/12 Acct1  Db 200  Cr 0  Bal +200 Runn Bal +400 

Closing balance until 26/7/12 = +400 

Page 2 
Opening balance until 26/7/12 = +450 (this is wrong - it should be the balance at the end of Page 1, but it is the balance until the 26/7/12 - i.e. includes the first item on Page 2) 
26/7/12 Acct1  Db 50  Cr 0  Bal +50  Runn Bal +500 (should be +450) 
27/7/12 Acct1  Db 60  Cr 0  Bal +60  Runn Bal +560 (should be +510) 

我只是想不出一個算法來處理這個問題。

任何想法?

回答

1

嗨,這是一個問題,我最近還面臨RavenDb,當我需要檢索任何可以想象的日期滾動的餘額。我從來沒有找到過這樣做的方法,但我管理的是減少了爲了計算滾動餘額而需要退回的文檔數量。

我寫多個地圖減少特定時期內總結了交易的價值指標做:

  1. 我首先總結了在今年的水平
  2. 我的第二個指標分組的所有交易的價值在一天的水平

所以,如果有人想他們的賬戶餘額截至6月1日總結了所有交易的價值2012我想:

  1. 使用Year級別Map-Reduce索引來獲取多達2012年的交易價值,並將它們彙總在一起(因此如果交易在2009年開始被捕獲,我應該撤回3份文件)
  2. 使用Day級別從一年的開始和6月1日開始獲取所有文檔的地圖縮小索引

然後我添加了日總計到年度總計爲我的最終滾動餘額(我也可以有一個月度地圖減少以及但沒有打擾)。

無論如何不像SQL那麼快,但它是我能想到的最好的選擇,以避免帶回每一筆交易