【问题标题】:Raven DB LINQ Where->Any Query not workingRaven DB LINQ Where->Any Query 不工作
【发布时间】:2013-08-19 14:57:39
【问题描述】:

我从 Raven DB 得到了一个奇怪的(非)结果。

我正在客户端和服务器上运行最新的稳定版本 v2.5.2666。

我要检索的是“第一个包含 Id 值为 'x' 的 Component 对象的 DeployProject 文档”。

所以我尝试的第一件事是:

var project = _documentSession.Query<DeployProject>()
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

但返回 null,即使我知道数据是正确的。为了验证我没有发疯,我在中间添加了一个 .ToList(),所以它会将所有文档拉出到内存中查询它。

var project = _documentSession.Query<DeployProject>()
      .ToList()
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

那确实有效,所以我的逻辑和数据是正确的。但是当然它确实效率很低,整个想法是我只想拉出包含相关子记录的单个文档。

所以 Raven 查询索引的方式肯定存在问题,因为数据肯定在那里,如果我将所有内容都拉入内存并运行相同的 LINQ 查询,我可以检索它。

我的希望(恐惧?)是索引过时了,所以我告诉它给我新的数据:

var project = _documentSession.Query<DeployProject>()
      .Customize(i=>i.WaitForNonStaleResultsAsOfLastWrite())
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

但我又一次得到了空值。似乎 Raven 只是没有按照我期望的方式处理 LINQ 语句,即 LINQ to objects 的工作方式。我知道可能存在一些差异,但这应该是一个非常简单的查询,我希望它可以工作。

有人有什么想法吗?我错过了一些简单的东西吗?

编辑:根据 Raven 的文档,这似乎应该在没有任何冒险索引的情况下工作:

http://ravendb.net/docs/client-api/querying/using-linq-to-query-ravendb

除了 Where 子句,还有其他几个有用的运算符 您可以用来过滤结果。

Any 可用于您的对象集合(或原始列表) 实体仅返回满足条件的实体。 RavenDB 也 支持 In 运算符,使反向任何比较更容易:

// Return only companies having at least one employee named "Ayende"
IQueryable<Company> companies = from c in session.Query<Company>()
                                where c.Employees.Any(employee => employee.Name == "Ayende")
                                select c;

【问题讨论】:

  • 投反对票?真的吗?有什么原因吗?
  • 在我看来,投反对票的是不理解问题的人。

标签: linq ravendb


【解决方案1】:

我认为这可能是类型问题,这很难看,但是您尝试过吗?

var project = _documentSession.Query<DeployProject>()
  .Where(i=>i.ComponentList.Any(j=>j.Id.ToString() == componentId.ToString()))
  .FirstOrDefault();

如果这可行,那么原始查询将比较两种不同的类型,并且没有正确转换其中一种。


试试这个,看看它是否能满足你的期望......

var project = _documentSession.Query<DeployProject>()
      .Where(i=>i.ComponentList.Any(j=>j.Id == componentId))
      .FirstOrDefault();

我知道应该是一样的,但是你可以用调试器这样测试它,看看返回了什么:

var project = _documentSession.Query<DeployProject>()
      .Where(i=>i.ComponentList.Any(j=>j.Id == componentId))
      .ToList()
      .FirstOrDefault();

【讨论】:

  • 相同的结果,我忽略了在我原来的问题中提到这一点(试图简洁),但是是的,我尝试将所有内容更改为 .Where 而不是 .FirstOrDefault 并且它仍然没有找到任何匹配的记录(当然,除非我将 .ToList() 移到 .Where 或 .FirstOrDefault 之前,在这种情况下我搜索的是内存而不是 Raven)
【解决方案2】:

首先,子选择根本不是很简单——从 raven / LINQ 的角度来看,这是一个非常复杂的查询。我会查看它创建的任何临时索引,看看它是否真的有效。

这里更好的方法是建立一个索引。让我印象深刻的两种方法是构建一个按 componentId 分组的索引,其中列出了部署项目。另一种方法是构建包含 componentId 的全文样式索引,然后您可以非常有效地使用 lucene 的导轨。

【讨论】:

  • 呃,我害怕这样的事情。 Raven 一直很棒,直到这样的点,直到答案开始是“手动创建一个 lucene 索引来映射减少转换哦,天哪,为什么这么难我只想找到包含某个记录的文档”:)
  • 另一个问题是 Raven 的文档说你应该能够做到这一点:ravendb.net/docs/client-api/querying/….
  • @MikeMooney -- 公平点虽然你对 SQL 有相同的心算,但我们已经习惯了它在这一点上被内化了 :)。此外,文档并没有暗示那里的第一个或默认行为——只是你可以获得 where 子句。在没有 first 或 default 的情况下进行检查,看看结果是什么,看看 ravendb 创建的索引是什么。我还会对一个版本进行回归测试,看看是否有帮助——可能是你发现的一个新的 2.5 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
相关资源
最近更新 更多