开发者

Querying Raven with Where() only filters against the first 128 documents?

We're using Raven to validate logins so people can get into our site.

What we've found is that if you do this:

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

The query only filters on the first 128 docs of the documents in Raven. There are several thousand in our database, so unless your email happens to be in that first 128 returned, you're out of luck.

None of the Raven samples code or any sample code I've come across on the net performs any looping using Skip() and Take() to iterate through the set.

  1. Is this the desired behavior of Raven?
  2. Is it the same behavior even if you use an advanced Lucene Query? ie; Do advanced queries behave any differently?
  3. Is the solution below appropriate? Looks a little ugly. :P

My solution is to loop through the set of all documents until I encounter a non null result, then I break and 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).Si开发者_开发百科ngleOrDefault();

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;

}

EDIT:

Using the fix below is not passing query params to my RavenDB instance. Not sure why yet.

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

In the end I am using Advanced Lucene Syntax instead of linq queries and things are working as expected.


RavenDB does not understand SingleOrDefault, so it performs a query without the filter. Your condition is then executed on the result set, but per default Raven only returns the first 128 documents. Instead, you have to call

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

so the filtering is done by RavenDB/Lucene.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜