【问题标题】:Ravendb map/reduce index not workingRavendb 映射/减少索引不起作用
【发布时间】:2017-02-09 13:29:58
【问题描述】:

我正在建立一个索引,但结果与预期不符。

我的目的是在 MyClass 的 SomeEnumFlag 中找到我有多少客户和供应商。 MyClass 有 Name 和 SomeEnumFlag,它是一种买卖文件。所以我可以有这样的文件:

{ Name: "Some company name", SomeEnumFlag: "Buy" },
{ Name: "Another company name", SomeEnumFlag: "Buy" },
{ Name: "Another company name", SomeEnumFlag: "Sell" },
{ Name: "Another company name", SomeEnumFlag: "Sell" }

预期结果是:

  • 客户:2;因为有两家不同的公司“买入”;
  • 供应商:1;因为有一家不同的公司“出售”

因此,基于SomeEnumFlag,一家公司可以是客户或/和供应商,我应该计算一次。

考虑索引:

public class MyClass_TotalClientsSuppliers_Index : AbstractIndexCreationTask<MyClass, MyClass_TotalClientsSuppliers_Index.Result>
{
    public class Result
    {
        public string Kind { get; set; }
        public int Total { get; set; }
    }

    public MyClass_TotalClientsSuppliers_Index()
    {
        Map = myClass => from grouped in myClass.GroupBy(c => new { Name = c.Name, Flag = c.SomeEnumFlag.ToString() })
                              select new
                              {
                                  Kind = grouped.Key.Flag,
                                  Total = 1
                              };

        Reduce = results => from result in results
                            group result by result.Kind into g
                            select new
                            {
                                Kind = g.Key,
                                Total = g.Sum(c => c.Total)
                            };
    }
}

和查询:

var resultTotalClientSupplier = session
                        .Query<MyClass_TotalClientsSuppliers_Index.Result, MyClass_TotalClientsSuppliers_Index>()
                        .ToList();

var totalClients = resultTotalClientSupplier.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Buy.ToString())?.Total ?? 0;
var totalSuppliers = resultTotalClientSupplier.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Sell.ToString())?.Total ?? 0;

totalClients = 2。

totalSuppliers = 2,错误。

但是,如果我写这样的代码:

var myClasses = session.Query<MyClass>().ToList();

var map = from grouped in myClasses.GroupBy(c => new { Name = c.Name, Flag = c.SomeEnumFlag.ToString() })
                              select new
                              {
                                  Kind = grouped.Key.Flag,
                                  Total = 1
                              };

var reduce = from result in map
                    group result by result.Kind into g
                    select new
                    {
                        Kind = g.Key,
                        Total = g.Sum(c => c.Total)
                    };

var totalClients = reduce.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Buy.ToString())?.Total ?? 0;
var totalSuppliers = reduce.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Sell.ToString())?.Total ?? 0;

totalClients = 2。

totalSuppliers = 1,没错!

我以完全相同的方式在内存中手动执行了 map/reduce 代码,并且它按预期工作。

我的索引有什么问题?我错过了什么?在索引中使用 group by 有一些限制吗?

提前致谢。

我应该提到,在 Map 方法中,我使用复合键进行了分组。所以 Name 和 SomeEnumFlag 应该像这两个属性之间的不同一样工作,总共有 3 个枚举({Some company name, Buy}、{Another company name, Buy}、{Another company name, Sell})。买多少? 2. 卖多少? 1. 乌鸦指数不工作。在模拟 map/reduce 行为的内存示例中,工作正常。

【问题讨论】:

  • 好的 - 我注意到了一件快事:在您的第一个代码示例中,您正在查询结果以获取结果。但是,在第二个示例中,您说事情进展顺利,您正在查询前一个变量“map”。这是一个简单的错字吗?
  • 是的,这是正确的,根据这个乌鸦文档ravendb.net/docs/article-page/3.5/csharp/indexes/…。 Map 产生结果,然后我可以在 Reduce 方法中查询结果。还有第二个注意,map是一个模拟Map方法的变量,所以map有分组查询。我的索引和 raven 文档之间的唯一区别是 Map 函数中的分组。

标签: c# ravendb


【解决方案1】:

我认为您的索引没有任何问题,我认为您的 LINQ 查询有问题。

假设只有 3 个项目,也许试试这个查询?

var totalSuppliers = reduce.Count(c => c.Kind == eSomeEnumFlag.Buy.ToString())

我认为这会缩短逻辑并使逻辑更加清晰,并且应该为您提供所需的内容?如果不让我知道,我会更深入地探讨。

【讨论】:

  • 我使用的示例只有 3 个项目,但在生产中它有数十万个,目标是在仪表板中显示用户拥有多少供应商和客户。你回答使用我的样本中的减少变量,这意味着我使用的内存方法,但我介意成千上万的文档。所以我想我应该在加载仪表板页面时使用索引来快速响应。
  • 啊,我的错误 - 现在再次查看您的原始代码
猜你喜欢
  • 2013-07-15
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多