【问题标题】:RavenDB ID getting messed up in code created indexRavenDB ID 在代码创建的索引中变得混乱
【发布时间】:2012-03-14 03:11:28
【问题描述】:

首先,我刚刚开始使用 RavenDB,所以请耐心等待我解释这个问题。我正在尝试创建我的第一个地图、地图、减少、转换索引。是的,我知道我正在尝试做很多事情,但我已经完成了大部分工作。

首先我在 global.asax 中执行此操作,以确保所有“ID”属性都用作文档的标识符。

_documentStore.Conventions.FindIdentityProperty = p => p.Name == "ID";

好的,现在让我们看看索引。

public class ProblemListViewIndex : AbstractMultiMapIndexCreationTask<ProblemListView>
{
    public ProblemListViewIndex()
    {
        AddMap<Problem>(problems => from problem in problems
                                    select new
                                    {
                                        ID = problem.ID,
                                        SolutionCount = 0,
                                    });

        AddMap<Solution>(solutions => from solution in solutions
                                      select new
                                      {
                                        ID = solution.ProblemID,
                                        SolutionCount = 1,
                                      });


        Reduce = results => from result in results
                            group result by result.ID
                                into g
                                select new
                                {
                                    ID = g.Key,
                                    SolutionCount = g.Sum(x => x.SolutionCount),
                                };

        Indexes.Add(x => x.ID, FieldIndexing.Analyzed);

        TransformResults = (database, results) => from result in results
                                                  let problem = database.Load<Problem>("problems/" + result.ID.ToString())
                                                  let user = database.Load<User>("users/" + problem.PostedByID.ToString())
                                                  select new
                                                  {
                                                      ID = result.ID,
                                                      PostedByID = problem.PostedByID,
                                                      PostedByName = user.DisplayName,
                                                      SolutionCount = result.SolutionCount,
                                                  };

    }
}

所以一切看起来都不错,当我在 RavenDB 网站上测试索引时,我得到了好坏参半的结果。我有重复的预测。我有我期望的两个预测,但有两个副本。以下是投影结果中“ID”的样子。

  • 问题/194
  • 问题/195
  • 194
  • 195

我很困惑,但后来我回去查看了“地图”。我的代码在创建的索引中翻译成不同的东西。这是最初创建第一张地图时的样子。

docs.Problems
    .Select(problem => new {ID = problem.__document_id, SolutionCount = 0})

即使是 RavenDB 的新手,我也看到了问题。当我想使用“ID”字段时,它正在使用“__document_id”字段。我更改了地图,然后将索引保存到以下内容。

docs.Problems
    .Select(problem => new {ID = problem.ID, SolutionCount = 0})

一旦我这样做了,我的投影就会完全符合我的预期和我想要的样子。

  • 194
  • 195

我的问题是我需要在我的代码中做什么才能使用“ID”而不是“__document_id”来创建索引?

【问题讨论】:

    标签: ravendb indexing


    【解决方案1】:

    我看不出这里有什么问题。我已经使用您的代码进行了测试,得到了我的预期:

    public class MultiMapWithTransformAndCustomId
    {
        public class Problem
        {
            public string ID { get; set; }
            public string PostedByID { get; set; }
            public string Foo { get; set; }
        }
    
        public class Solution
        {
            public string ID { get; set; }
            public string ProblemID { get; set; }
            public string Foo { get; set; }
        }
    
        public class User
        {
            public string ID { get; set; }
            public string DisplayName { get; set; }
        }
    
        public class ProblemListViewIndex : AbstractMultiMapIndexCreationTask<ProblemListViewIndex.ReduceResult>
        {
            public class ReduceResult
            {
                public string ID { get; set; }
                public int SolutionCount { get; set; }
                public string PostedByID { get; set; }
                public string PostedByName { get; set; }
            }
    
            public ProblemListViewIndex()
            {
                AddMap<Problem>(problems => from problem in problems
                                            select new
                                            {
                                                ID = problem.ID,
                                                SolutionCount = 0,
                                            });
    
                AddMap<Solution>(solutions => from solution in solutions
                                              select new
                                              {
                                                  ID = solution.ProblemID,
                                                  SolutionCount = 1,
                                              });
    
    
                Reduce = results => from result in results
                                    group result by result.ID
                                        into g
                                        select new
                                        {
                                            ID = g.Key,
                                            SolutionCount = g.Sum(x => x.SolutionCount),
                                        };
    
                Indexes.Add(x => x.ID, FieldIndexing.Analyzed);
    
                TransformResults = (database, results) => from result in results
                                                          let problem = database.Load<Problem>(result.ID.ToString())
                                                          let user = database.Load<User>(problem.PostedByID.ToString())
                                                          select new
                                                          {
                                                              ID = result.ID,
                                                              PostedByID = problem.PostedByID,
                                                              PostedByName = user.DisplayName,
                                                              SolutionCount = result.SolutionCount,
                                                          };
    
            }
        }
    
        [Fact]
        public void Can_do_simple_query()
        {
            using (var documentStore = new EmbeddableDocumentStore
            {
                RunInMemory = true
            })
            {
                documentStore.Conventions.FindIdentityProperty = p => p.Name == "ID";
                documentStore.Initialize();
    
                using (var documentSession = documentStore.OpenSession())
                {
                    documentSession.Store(new User {ID = "users/1", DisplayName = "Daniel"});
                    documentSession.Store(new User {ID = "users/2", DisplayName = "Lang"});
                    documentSession.Store(new Problem {ID = "problems/194", PostedByID = "users/1"});
                    documentSession.Store(new Problem {ID = "problems/195", PostedByID = "users/2"});
                    documentSession.Store(new Solution {ID = "solutions/1", ProblemID = "problems/194"});
                    documentSession.Store(new Solution {ID = "solutions/2", ProblemID = "problems/194"});
                    documentSession.Store(new Solution {ID = "solutions/3", ProblemID = "problems/195"});
                    documentSession.SaveChanges();
                }
    
                new ProblemListViewIndex().Execute(documentStore);
    
                using (var documentSession = documentStore.OpenSession())
                {
                    var results = documentSession.Query<ProblemListViewIndex.ReduceResult, ProblemListViewIndex>()
                        .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
                        .ToList();
    
                    Assert.Equal(2, results.Count);
    
                    var daniel = results.First(x => x.PostedByName == "Daniel");
                    var lang = results.First(x => x.PostedByName == "Lang");
    
                    Assert.Equal("problems/194", daniel.ID);
                    Assert.Equal("problems/195", lang.ID);
                }
            }
        }
    }
    

    【讨论】:

    • 您使用字符串作为 ID。我正在使用整数。
    • Bobby,你能修改我上面的代码,让它失败并发送给我吗?如果可能的话,我会在 RavenDB 中解决这个问题。
    • 我已将更新后的代码通过电子邮件发送给您。我还意外编辑了您的答案。我今天早上跳得太早了……需要咖啡。
    • 我将此标记为答案,但我仍然觉得如果 RavenDB 不能将整数作为索引处理,那么它不应该允许它。感谢您的帮助。
    【解决方案2】:

    我也发现了这个问题,我找到了一种解决方法,方法是在我的索引中添加另一个字段,例如 SolutionId,并将其值设置为与 Id 相同。

    然后您应该能够针对该值运行查询而不会出现任何问题。

    我之前在这里问过同样的问题,显然这是设计使然。

    【讨论】:

    • 哦,我不能那样做。我会发疯的……说真的,我是一个干净的代码狂热者。如果我有两个字段总是相同的数据,我将无法在晚上睡觉。哈哈。
    【解决方案3】:

    除了 Daniel 所说的,solution.ProblemID 是一个整数字段。

    最简单的解决方案是将解决方案图更改为:

        ID = "problems/" + solution.ProblemID,
    

    但我强烈建议您使用字符串引用,而不是整数引用,这会使一切变得更简单。

    【讨论】:

    • 您确实看到了问题。 RavenDB 据说支持“int”键,但随后会破坏索引,因为它会更改键名。为什么索引不能只留下名称?为什么 RavenDB 一定要改属性名?
    • 哦,管理站点会正确保存。从代码创建时无法正确创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-28
    • 2021-12-31
    相关资源
    最近更新 更多