7

我们正在使用 Raven 验证登录,以便人们可以进入我们的网站。

我们发现,如果你这样做:

// Context is an IDocumentSession 
Context.Query<UserModels>()
           .SingleOrDefault(u => u.Email.ToLower() == email.ToLower()); 

该查询仅过滤 Raven 中文档的前 128 个文档。我们的数据库中有几千个,所以除非您的电子邮件恰好在返回的前 128 个中,否则您就不走运了。

我在网上遇到的 Raven 示例代码或任何示例代码都没有使用 Skip() 和 Take() 执行任何循环来遍历集合。

  1. 这是 Raven 想要的行为吗?
  2. 即使您使用高级 Lucene 查询,行为是否相同?IE; 高级查询的行为有什么不同吗?
  3. 下面的解决方案合适吗?看起来有点丑。:P

我的解决方案是遍历所有文档的集合,直到遇到非空结果,然后我 break 并 return 。

public T SingleWithIndex(string indexName, Func<T, bool> where)
{
    var pageIndex = 1;
    const int pageSize = 1024;
    RavenQueryStatistics stats;

var queryResults = Context.Query<T>(indexName)
    .Statistics(out stats)
    .Customize(x => x.WaitForNonStaleResults())
    .Take(pageSize)
    .Where(where).SingleOrDefault();

if (queryResults == null && stats.TotalResults > pageSize)
{
    for (var i = 0; i < (stats.TotalResults / (pageIndex * pageSize)); i++)
    {
        queryResults = Context.Query<T>(indexName)
            .Statistics(out stats)
            .Customize(x => x.WaitForNonStaleResults())
            .Skip(pageIndex * pageSize)
            .Take(pageSize)
            .Where(where).SingleOrDefault();

        if (queryResults != null) break;

        pageIndex++;
    }

}

return queryResults;

}

编辑:

使用下面的修复不会将查询参数传递给我的 RavenDB 实例。还不知道为什么。

Context.Query<UserModels>()
    .Where(u => u.Email == email)
    .SingleOrDefault();

最后,我使用了 Advanced Lucene Syntax 而不是 linq 查询,并且一切都按预期工作。

4

1 回答 1

4

RavenDB 不理解SingleOrDefault,因此它执行没有过滤器的查询。然后在结果集上执行您的条件,但默认情况下,Raven 仅返回前 128 个文档。相反,您必须致电

Context.Query<UserModels>()
       .Where(u => u.Email == email)
       .SingleOrDefault();

所以过滤是由 RavenDB/Lucene 完成的。

于 2011-02-24T13:14:29.303 回答