2012-07-07 23 views
1

对不起这个冗长的查询,我决定添加整个测试,这样即使是新手也能帮助我完成整个脑融合。RavenDB MultiMapReduce总和没有返回正确的值

的使用指令是:

using System.Collections.Generic; 
using System.Linq; 
using NUnit.Framework; 
using Raven.Client; 
using Raven.Client.Embedded; 
using Raven.Client.Indexes; 

请留下反馈意见,如果我太冗长,但什么可能出问题,如果我加一个完整的测试?

[TestFixture] 
public class ClicksByScoreAndCardTest 
{ 
    private IDocumentStore _documentStore; 

    [SetUp] 
    public void SetUp() 
    { 
     _documentStore = new EmbeddableDocumentStore {RunInMemory = true}.Initialize(); 
     _documentStore.DatabaseCommands.DisableAllCaching(); 

     IndexCreation.CreateIndexes(typeof (ClicksBySearchAndProductCode).Assembly, _documentStore); 
    } 

    [TearDown] 
    public void TearDown() 
    { 
     _documentStore.Dispose(); 
    } 

    [Test] 
    public void ShouldCountTotalLeadsMatchingPreference() 
    { 
     var userFirst = new User {Id = "users/134"}; 
     var userSecond = new User {Id = "users/135"}; 
     var searchFirst = new Search(userFirst) 
           { 
            Id = "searches/24", 
            VisitId = "visits/63" 
           }; 
     searchFirst.Result = new Result(); 
     searchFirst.Result.Rows = new List<Row>(
      new[] 
       { 
        new Row {ProductCode = "CreditCards/123", Score = 6}, 
        new Row {ProductCode = "CreditCards/124", Score = 4} 
       }); 

     var searchSecond = new Search(userSecond) 
           { 
            Id = "searches/25", 
            VisitId = "visits/64" 
           }; 

     searchSecond.Result = new Result(); 
     searchSecond.Result.Rows = new List<Row>(
      new[] 
       { 
        new Row {ProductCode = "CreditCards/122", Score = 9}, 
        new Row {ProductCode = "CreditCards/124", Score = 4} 
       }); 

     var searches = new List<Search> 
          { 
           searchFirst, 
           searchSecond 
          }; 

     var click = new Click 
         { 
          VisitId = "visits/64", 
          ProductCode = "CreditCards/122", 
          SearchId = "searches/25" 
         }; 

     using (var session = _documentStore.OpenSession()) 
     { 
      foreach (var search in searches) 
      { 
       session.Store(search); 
      } 
      session.Store(click); 
      session.SaveChanges(); 
     } 

     IList<ClicksBySearchAndProductCode.MapReduceResult> clicksBySearchAndProductCode = null; 
     using (var session = _documentStore.OpenSession()) 
     { 
      clicksBySearchAndProductCode = session.Query<ClicksBySearchAndProductCode.MapReduceResult>(ClicksBySearchAndProductCode.INDEX_NAME) 
       .Customize(x => x.WaitForNonStaleResults()).ToArray(); 
     } 
     Assert.That(clicksBySearchAndProductCode.Count, Is.EqualTo(4)); 
     var mapReduce = clicksBySearchAndProductCode 
      .First(x => x.SearchId.Equals("searches/25") 
         && x.ProductCode.Equals("CreditCards/122")); 
     Assert.That(mapReduce.Clicks, 
       Is.EqualTo(1)); 
    } 
} 

public class ClicksBySearchAndProductCode : 
    AbstractMultiMapIndexCreationTask 
     <ClicksBySearchAndProductCode.MapReduceResult> 
{ 
    public const string INDEX_NAME = "ClicksBySearchAndProductCode"; 

    public override string IndexName 
    { 
     get { return INDEX_NAME; } 
    } 

    public class MapReduceResult 
    { 
     public string SearchId { get; set; } 
     public string ProductCode { get; set; } 
     public string Score { get; set; } 
     public int Clicks { get; set; } 
    } 

    public ClicksBySearchAndProductCode() 
    { 
     AddMap<Search>(
      searches => 
      from search in searches 
      from row in search.Result.Rows 
      select new 
      { 
       SearchId = search.Id, 
       ProductCode = row.ProductCode, 
       Score = row.Score.ToString(), 
       Clicks = 0 
      }); 
     AddMap<Click>(
      clicks => 
      from click in clicks 
      select new 
      { 
       SearchId = click.SearchId, 
       ProductCode = click.ProductCode, 
       Score = (string)null, 
       Clicks = 1 
      }); 
     Reduce = 
      results => 
      from result in results 
      group result by 
       new { SearchId = result.SearchId, ProductCode = result.ProductCode } 
       into g 
       select 
        new 
        { 
         SearchId = g.Key.SearchId, 
         ProductCode = g.Key.ProductCode, 
         Score = g.First(x => x.Score != null).Score, 
         Clicks = g.Sum(x => x.Clicks) 
        }; 
    } 
} 
public class User 
{ 
    public string Id { get; set; } 
} 

public class Search 
{ 
    public string Id { get; set; } 
    public string VisitId { get; set; } 
    public User User { get; set; } 

    private Result _result = new Result(); 

    public Result Result 
    { 
     get { return _result; } 
     set { _result = value; } 
    } 

    public Search(User user) 
    { 
     User = user; 
    } 
} 

public class Result 
{ 
    private IList<Row> _rows = new List<Row>(); 

    public IList<Row> Rows 
    { 
     get { return _rows; } 
     set { _rows = value; } 
    } 
} 

public class Row 
{ 
    public string ProductCode { get; set; } 
    public int Score { get; set; } 
} 

public class Click 
{ 
    public string VisitId { get; set; } 
    public string SearchId { get; set; } 
    public string ProductCode { get; set; } 
} 

我在这里的问题是,我希望计数是一个在特定的测试,但它只是似乎没有添加点击在点击地图,结果是0点击。我完全困惑,我敢肯定,有一个非常简单的解决方案来解决我的问题,但我无法找到它..

..希望有一个周末的战士谁可以把我放在他的翅膀下。

+0

很抱歉打扰你,我发现F中的错误/ ***了.. 精神注意,使用: 得分= g.Select(X => x.Score).FirstOrDefault() 唐't use: Score = g.First(x => x.Score!= null).Score – Molibar 2012-07-07 11:57:54

回答

1

是的,这对我来说是一个脑筋急转弯,对我而言并不重要,但依然如此。适当的减少应该是这样的:

Reduce = 
    results => 
    from result in results 
    group result by 
     new { SearchId = result.SearchId, ProductCode = result.ProductCode } 
     into g 
     select 
      new 
      { 
       SearchId = g.Key.SearchId, 
       ProductCode = g.Key.ProductCode, 
       Score = g.Select(x=>x.Score).FirstOrDefault(), 
       Clicks = g.Sum(x => x.Clicks) 
      }; 

并非所有的地图有分数设置为一个非空值,因此,我原来的版本有一个问题:

Score = g.First(x => x.Score != null).Score 

心理笔记,用途:

Score = g.Select(x=>x.Score).FirstOrDefault() 

不要使用:

Score = g.First(x => x.Score != null).Score